Description
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;
}
}