In D8:
File field's Maximum upload size is validated by:
<?php
public static function validateMaxFilesize($element, FormStateInterface $form_state) {
if (!empty($element['#value']) && !is_numeric(Bytes::toInt($element['#value']))) {
$form_state->setError($element, t('The "!name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', array('!name' => t($element['title']))));
}
}
?>
This function has 2 bugs:
- It will always validate because Bytes::toInt() always returns a number.
- It is not $element['title'] but $element['#title']
In D7:
File field's Maximum upload size is validated by:
<?php
function _file_generic_settings_max_filesize($element, &$form_state) {
if (!empty($element['#value']) && !is_numeric(parse_size($element['#value']))) {
form_error($element, t('The "!name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', array('!name' => t($element['title']))));
}
}
?>
This function has 2 bugs:
- It will always validate because parse_size() always returns a number.
- It is not $element['title'] but $element['#title']
Comments
Comment #1
anrikun commentedHere is a patch.
Comment #2
anrikun commentedThe same bug is also present in 8.0.x
Comment #3
anrikun commentedComment #4
jhedstromThis adds a test.
Comment #7
jhedstromWeird. I didn't notice the
t()function when testing locally these worked for some reason.Comment #8
jhedstromI'm guessing this won't be allowed, but Views does it, and it illustrates the fix. I could have sworn there was an issue out there somewhere to add
\Drupal::t()for use in static methods like this, but I couldn't find it.Comment #10
mgiffordNeeds re-roll.
Comment #19
grimreaperComment #20
grimreaperManually testing because It seems that the "It will always validate because Bytes::toInt() always returns a number." part had been fixed in #3142934: Replace \Drupal\Component\Utility\Bytes::toInt() with \Drupal\Component\Utility\Bytes::toNumber() due to return type.
Comment #21
grimreaperOk, my bad I was not testing the right thing.
I was testing the upload in a field. Not the settings form of the field...
Confirming that there is still the bug.
Comment #23
grimreaperMR created, I have removed an unused statement in the test file. And kept the "@name" instead of changing into "!name".
I don't know if credits will be applied properly as selectin "author" and "by" does not change the commit command and I didn't commit with my drupal.org user account email address.
Comment #24
grimreaperFail related to #2458387: Remove Utility\String class. Fixing.
Comment #25
grimreaperComment #26
lendudeNot sure what we want to do with the commented out test cases
Comment #27
grimreaperYes, me too, that's why I need some feedbacks :). Replied in the MR.
Comment #28
grimreaperFor the record, when uncommeting thelines, this is the warning message:
Comment #29
grimreaperComment #30
lendudeAdded some feedback to the MR
Comment #31
grimreaperThanks @Lendude for the review.
Test cases added.
Comment #32
liber_tGood for me
Comment #33
rachel_norfolkJust doing a little tag tidying. Nice work everyone!!
Comment #34
alexpottDo we need to check that current values are valid? I think it is okay... atm invalid values like 'five' will be determined to be 0 which means that it will be ignored in
file_validate_size(). The user will then be prompted to fix this if they save the field again.Maybe we should consider adding a Bytes::validate() method to validate a string representation and use that here? For example '1five' is still considered valid!
And would result in a v. large maximum filesize.
If we added a generic string validation method on the utility class then anywhere else that accepts a byte string could use it.
Comment #35
grimreaperComment #36
grimreaperHello,
validate method added to the Bytes utility class as asked in comment 34.
I kept the test for the validateMaxFilesize method.
I made an allowed suffixes constant to avoid side effects and not catched cases with regex. If there is a better approach, please suggest.
Thanks for the review.
Comment #37
grimreaperChecking.
Comment #38
grimreaperTests are back to green.
Thanks for the review.
Comment #39
grimreaperComment #40
grimreaperTests added.
Ready fo review again.
Comment #41
grimreaperComment #42
dwwNW for the review points in the MR.
Also, is it worth a functional test showing end-to-end that a bogus value for this limit can be saved and then ignored by uploading a real file? I'd feel a bit safer RTBC'ing this if we weren't only testing the lowest level parts of this, but actually seeing the real bug we're fixing as a test-only fail that becomes green with the rest of the fix applied...
Comment #43
grimreaperComment #44
grimreaperHello,
Thanks @dww for the review!
Review points taken into account except one https://www.drupal.org/project/drupal/issues/2359675#mr127-note20090 for which I am waiting more people opinion.
About comment #2359675-42: File field's Maximum upload size always passes validation, I am not sure to understand what you mean because the bug is on the field config form, not on an entity form. So I don't think this is needed to go to the point to test a file upload.
Also with this patch it is now not possible to configure a bad value for the maximum upload size, so how did you imagine such test?
Comment #45
nicoloye commentedThe proposed MR seems ok to me !
Comment #46
larowlanComment #47
paulocsI'll work on it.
Set back to nw because of #46.
Comment #48
paulocsI didn't create a trait as @larowlan pointed bacause if we trim the input, the list must be edited so they get different between each other.
I didn't addressed what @dww pointed because as the lists are different I'm not sure what the best approach is.
Maybe we can reduce the list in
FileItemTestjust to the tests cases that are different from list inBytes.php?Comment #49
paulocsI addressed what @larowlan and @dww pointed.
Please review!
Cheers, Paulo.
Comment #51
grimreaperI have pointed out to Slack that the issue version is 10.0.x-dev where comment 50 assigned it to version 9.3.x-dev (https://drupal.slack.com/archives/C51GNJG91/p1619869940156900)
Thanks @paulocs for the update.
I will complete a little bit the functional test.
Comment #52
grimreaperFunctional test completed.
Needs review!
Comment #53
grimreaperComment #54
paulocsFor me it looks good!
Comment #55
grimreaperHello,
Just poking the issue, I don't think there is anything left to be done :)
Comment #56
larowlanHi @Grimreaper, @paulocs this looks good to me, I have just one comment about an extra test case.
Please feel to ping me for another look when this is ready.
Lee
Comment #59
larowlanSaving issue credits
Comment #61
catch(whoops, cross-post with larowlan).
Looks good to me as well.
I had to think for a bit about toNumber() being able to translate units without needing the list of allowed values, vs validation needing an explicit list, but I think this is fine .
toNumber()is doing some trickery with string ordering and powers, which will allow some 'invalid' values (i.e. it would accept killerbytes because it's only looking for 'k'), but there's no reason to make that more restrictive, or to make the validation less restrictive, because they're doing different things.Committed/pushed to 9.3.x and cherry-picked to 9.2.x, thanks!
Comment #62
catchRe-opening for discussion - but we should either roll back or open a follow-up rather than commit two patches.
Comment #63
grimreaperHello,
Thanks @larowlan for the review.
Ok to write a new test in a follow-up issue. Can someone just give some advice on what to write exactly please?
@catch thanks for the commits!
Comment #64
paulocsHello Grimreaper,
I think we should add
'300 0'toproviderTestValidate.I'll open a follow-up issue to add the test.
Comment #65
paulocsFollow-up issue: #3218711: Add a test case for when Maximum upload size is '300 0'
Comment #66
catchThanks for opening the follow-up, marking this fixed again.
Comment #67
grimreaper@paulocs Thanks for the follow-up issue.
Ok, clear now, I didn't realize it was the "$string = '300 0';" the use case of the online example, sorry.
Comment #69
catchMarked this eleven year old issue as duplicate #870576: Insufficient validation of the max upload file size field.
Comment #70
thursday_bw commented@catch
Is it just an oversite that credit was not assigned for all the effort put into to https://www.drupal.org/project/drupal/issues/870576 ?
It is heartedly discouraging to put significant effort into an issue simply to have it all thrown away by a duplicate issue.
Comment #76
larowlan@bevan.wishart@gmail.com yeh that was definitely an oversight mate - copying over the credit from the other issue.
Feel free to ask if this happens again, we're all human