Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP: unequal numeric strings (and byte arrays) are compared as equal #1217

Open
generalmimon opened this issue Jan 6, 2025 · 0 comments
Open

Comments

@generalmimon
Copy link
Member

Reproducible example:

meta:
  id: str_eq
instances:
  eq_strings:
    value: '"7" == "07"'
  eq_byte_arrays:
    value: '[0x37] == [0x30, 0x37]'

As of kaitai-io/kaitai_struct_compiler@12dbc32, it is translated to PHP as follows:

        protected $_m_eqStrings;
        public function eqStrings() {
            if ($this->_m_eqStrings !== null)
                return $this->_m_eqStrings;
            $this->_m_eqStrings = "7" == "07";
            return $this->_m_eqStrings;
        }
        protected $_m_eqByteArrays;
        public function eqByteArrays() {
            if ($this->_m_eqByteArrays !== null)
                return $this->_m_eqByteArrays;
            $this->_m_eqByteArrays = "\x37" == "\x30\x37";
            return $this->_m_eqByteArrays;
        }

Both eq_strings and eq_byte_arrays should evaluate to false, but they evaluate to true in the generated PHP parser. The reason is written in PHP documentation:

If both operands are numeric strings, or one operand is a number and the other one is a numeric string, then the comparison is done numerically. These rules also apply to the switch statement. The type conversion does not take place when the comparison is === or !== as this involves comparing the type as well as the value.

The solution would be to use the strict equality operator === instead, which does not perform type juggling. The catch I can foresee is that simply switching entirely to === would break expressions like 2.0 == 2 (which the KS expression language apparently allows), since float and int are different types (var_dump(2.0 === 2) is bool(false)).

We should also pay attention to this part:

These rules also apply to the switch statement.

This means that we run into the same problem with type switching, because this .ksy snippet...

seq:
  - id: a
    type:
      switch-on: '"7"'
      cases:
        '"07"': s1

... is translated into a switch statement:

        private function _read() {
            switch ("7") {
                case "07":
                    $this->_m_a = $this->_io->readS1();
                    break;
            }
        }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant