Stack overflow in message decoding
The problem has been detected by OSS-Fuzz. The fixing commit message shall include Credit to OSS-Fuzz
.
Description
The decode_fuzzer
crashes with a Stack Overflow when decoding a lot of nested DataValues/Variants/ExtensionObjects.
(The reproducer is available here.)
Analysis
Variant and DataValue limit the number of nested items using a parameter nestedVariantLevel
(increasing with the nesting level) and compare it with a constant SOPC_MAX_VARIANT_NESTED_LEVEL
.
However the ExtensionObject does not propagate this nested level and resets it to 0 (if it contains a Variant). The stack overflow happens because of this flaw.
Chosen Solution
Use a nestedStructLevel
instead of a nestedVariantLevel
and pass it to all decoders (builtins and generic).
Delete the now useless SOPC_MAX_VARIANT_NESTED_LEVEL
and create a new constant SOPC_MAX_STRUCT_NESTED_LEVEL
.
Compare the nestedStructLevel
with SOPC_MAX_STRUCT_NESTED_LEVEL
in every decoder.
Increment the nestedStructLevel
with each decoder call.
Start decoding with nestedStructLevel
equal to 0.
-
The reproducer shall be included in the decode_fuzzer
corpus.
(Another solution was to flatten the recursion, but it requires a massive rework of the decoding process.)
Edit: After finishing a successful implementation of this solution, the decode_fuzzer
noted that we could not encode anymore what we just decoded. This is due to the SOPC_MAX_VARIANT_NESTED_LEVEL
that is still present in the encoding. A discussion with the dev team lead to the statement that encoding and decoding should be symmetric. Hence, the same recursion limit should be applied for encoding and decoding. Moreover, this modification will enforce safety since the app user could pass structures directly to the encoder and the same stack overflow might happen for encoding.
-
Launch the decode_fuzzer
for quite some time (Done: 30M tests)