Problem/Motivation
Since PHP 8.1, Deprecation notices are ensuring type safety on more standard functions.
This includes mb_strlen, called in drupal_strlen.
If NULL is passed to drupal_strlen, the following deprecation notice will triggers:
mb_strlen() expects parameter 1 to be string, array given in .../drupal/includes/unicode.inc on line 482.Steps to reproduce
When $elements['#value'] is NULL, and $elements['#maxlength'] is set, on PHP 8.1, the deprecation notice will triggers during form validation
Proposed resolution
Added an isset check before calling drupal_strlen.
This function make a lot of isset check above and below, so having a null value here seems expectable.
Prevent that null value to be passed by drupal_strlen.
| Comment | File | Size | Author |
|---|
Issue fork drupal-3362238
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3362238-formvalidate-sends-null
changes, plain diff MR !4309
Comments
Comment #2
DeanThomas commentedComment #3
poker10 commentedThanks for reporting this @DeanThomas and for providing a patch!
I think we should add a test for this behavior. Then we can consider if we are going to fix this as proposed in patch #2, or use more global approach and fix the problem directly in
drupal_strlen()by casting the$textto string (as we have done in few others, likedrupal_substr(), see: #3241422: [PHP 8.1] Passing `null` to internal functions deprecation fixes).Comment #4
gbirch commentedAs mentioned in my late comments on a closed issue (https://www.drupal.org/project/drupal/issues/3270881), it seems to me that the right, developer-friendly answer is to make drupal_strlen() behave as it does in PHP 7 when passed a NULL value - it should simply return 0.
I'm not sure what the right answer should be when handling other variable types: arrays, objects, scalar values. Casting to string can result in odd behavior - in particular the function will return 5 if given (string) $array, which just seems wrong and unhelpful. But perhaps that's a question for another day, as the vast majority of errors seem likely to be the result of passing NULL.
In short, can we just do https://www.drupal.org/project/drupal/issues/3270881#comment-15027276 and call it a day? I'm happy to produce a patch or fork if that seems like the right answer. I'm not sure where a test should go - in UnicodeUnitTest?
Comment #5
poker10 commentedI think we should not change the behavior for other data types like array, objects, ..., as it would mask the problem for developers/users in case they are passing a non-string here. The most safe approach is, as you have mentioned, to check if the string is
NULLand if yes, then return 0.For the test - yes, we can add a NULL key to the
UnicodeUnitTest::helperTestStrLen()to test thedrupal_strlen()itself, but I was thinking about testing the the usecase mentioned in the issue summary -. This would be more suited to the
form.testfile.Thanks!
Comment #7
gbirch commented@poker10
I have added the fix, a unicode test (easy), and a form validation test (harder - as there was no existing test for maxlength validation).
Comment #8
poker10 commentedThanks! Triggering tests on the new merge request.
Comment #9
poker10 commentedI have added some minor comments to the MR. In overall it looks good!
I have tried the test-only patch and I suppose this should fail?
But for some reason, it is not failing for me (in test-only patch).
Thanks!
Comment #11
poker10 commentedAfter the recent changes, the MR is failing because the
machine_nameelement is missing some required properties. I suggest that we skip testing themachine_nameelement and keep onlypasswordandtextfieldhere.Anyway, I am still not able to get the error from the IS
with the test-only patch (using the NULLs) even after removing the machine_name element.
I am not sure if we are not experiencing the similar problem as I have figured out here: #1224674-5: Type checking in function _form_validate in form.inc, e.g. that the deprecation message is caused by another element type - not
textfield,password,machine_name, but some element, likeselect, where you can actually passNULL.Comment #12
joelpittetAdding to #3366270: [meta] Priorities for 2023-12-06 release of Drupal 7
Comment #13
poker10 commentedI have implemented my own feedback from the MR :) Also updated the MR so that the test-only pipeline can be run.
Test-only job failed as expected: https://git.drupalcode.org/project/drupal/-/jobs/1306529
Fix+test pipeline is green as expected: https://git.drupalcode.org/project/drupal/-/pipelines/144322
Moving to Needs review, so hopefully we can finish this.
Comment #14
poker10 commentedAdding a tag for the final review.
Comment #16
mcdruid commentedI'm a bit surprised that there's apparently no existing test of Form API's maxlength but indeed.. I don't see one.
This looks like a good change / BC layer, thanks all!