@BR0kEN - it's the lack of the third argument and it not being TRUE that scares me. Pretty much people always want
in_array($needle, $haystack, TRUE)and notin_array($needle, $haystack)- see https://3v4l.org/sr29Y
Problem/Motivation
Normalizer could define type(s) of data which they wants to normalize using supportedInterfaceOrClass property of \Drupal\serialization\Normalizer\NormalizerBase. The same available for request types, which are accepted by normalizer (using format property).
In both cases these properties will be casted to an array to be handled by in_array() function to find the matches and, in both cases, this will happen without strict data comparison which could cause potential inconsistences.
Proposed resolution
AddTRUEas third argument to everyin_array()function in\Drupal\serialization\Normalizer\NormalizerBase- Add tests
| Comment | File | Size | Author |
|---|---|---|---|
| #55 | 2864495-strict-mode-for-denormalization-in-core.patch | 4.12 KB | yevko |
| #40 | 2864495-40.patch | 4.8 KB | br0ken |
Issue fork drupal-2864495
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:
Comments
Comment #2
wim leersComment #3
wim leersComment #4
damiankloip commentedI think we could just add the third parameter to the in_array() call in supportsDenormalization(), not sure what other tests we need there? I guess we can just add a couple of tests to \Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization.
The !isset() vs empty() for the $format check, I'm not sure of the benefits. If it's something empty like '' or 0 it's unlikely that the format property will match that. Seems like too much baby sitting, potentially?
Comment #5
wim leers#4 sounds sensible. Removed point 2 from the IS per #4.
Everything except the tests should be doable by a novice, so adding tags.
Comment #6
damiankloip commented+++ Thanks, Wim!
Comment #7
dinesh18 commentedHere is the patch which adds third argument TRUE to in_array functions.
Comment #8
wim leersThanks! Now task 1 is done. Updated issue summary.
Now task 2 remains.
Comment #9
dinesh18 commentedThanks Wim for reviewing the patch.
Could you please help me how to create Tests as I am creating it for the first time.
Comment #10
damiankloip commentedPlease see comment #4, I think the test I mentioned there can be added to, to cover this edge case.
Comment #11
dinesh18 commentedThanks damiankloip. I will work on the Tests as mentioned in #4
Comment #12
dinesh18 commentedTest case : \Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization
if (!isset($format) && empty($format)) {
$this->assertNull($format, 'Null Value');
}
Could you please manually review if it looks good so that I can create the patch.
Comment #13
wim leers\Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization()is testingsupportsNormalization(). The change made in #7 modifiessupportsDenormalization().So it's not quite correct yet, but you're thinking along the right lines.
The point here is: add a test that fails if #7 is not applied, and hence demonstrates the bug. Then apply #7, and the test should pass.
Comment #14
damiankloip commentedRight. You will want to add a new test method (and data provider maybe) for supportsDenormalization I think.
Comment #16
wim leersPinged @Dinesh18.
Comment #17
dinesh18 commentedI have tried creating one default function testSupportsDenormalization() mentioned below. It is hard-coded which always returns TRUE.
Could you please help me how can I pass values to
function supportsDenormalization($data, $type, $format = NULL).Comment #18
wim leers@Dinesh18: you want to create a "data provider" function. See
\Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::testSupportsNormalization()'s docblock +\Drupal\Tests\serialization\Unit\Normalizer\NormalizerBaseTest::providerTestSupportsNormalization()for an example.Comment #19
ivan berezhnov commentedComment #21
jamesdixon commentedI'll take a crack at writing this test at the PNWDS.
Comment #22
jamesdixon commentedHere's my attempt at testSupportsDenormalization. This test should have 3 failures with the current patch because I did not include the solution in#7.
Comment #23
jamesdixon commentedThis new patch includes the fix in #7 and should pass all tests.
Comment #24
jamesdixon commentedComment #25
borisson_This should be
TestNormalizerBase::class, to make refactoring easier.This data provider should also test positive return values, not just negative return values.
So at least one of them shuold be
Comment #26
savkaviktor16@gmail.com commentedComment #27
borisson_Awesome, thanks for fixing those @Saviktor. This looks done.
Comment #28
br0kenPHPCS: Parameter tags must be defined first in a doc comment.
The #4 argument must have a default value defined.
Avoid mixing the
array()and[].Comment #29
savkaviktor16@gmail.com commentedComment #30
savkaviktor16@gmail.com commentedComment #31
br0kenLet's have
nullas the default value since it means "really nothing" in comparison to an empty array, which is an empty value. Thereforeisset()can be returned back.Comment #32
mohit1604 commentedComment #33
mohit1604 commentedDid changes as per comment #31, please review it :)
Comment #34
andypostthen makes sense to change condition to
isset()Comment #35
br0kenAgree with the above.
Comment #36
wim leersThis is always
new \stdClass, so there's no need to pass it in.These comments should be the keys to the test cases: that's how you label test cases. Then if a test case fails, you get that label instead of a number!
Comment #37
br0kenComment #38
br0kenThe other problem I see is that the
supportsDenormalization()might return an array instead of boolean.I've taken method's params and their types from the original class.
This should be prevented somehow IMO.
Comment #39
br0kenIn my imagination, it should be something like that. Please review.
Comment #40
br0kenExtended tests coverage plus added documentation.
Comment #41
wim leersThis patch is now changing much more.
When can this ever be an object? That is not actually allowed by
\Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization().This is not actually allowed to contain an int or a float. Again, see
\Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization().Comment #42
br0kenThen why do we need
in_array()withTRUE?Comment #51
rosk0I would really love to see something like
META Use strict mode for "in_array()" callsas parent of this to fix this big bug possibility once and for all the core.RE #42 - read issue description and check the link there.
Comment #54
andypostComment #55
yevko commentedHere is a patch for 11.2.3 based on #40
https://www.drupal.org/files/issues/2025-09-03/2864495-strict-mode-for-d...