Skip to content

Commit 3acacac

Browse files
authored
Fix validation of unused LEB128 bits (#6680)
The unused bits must be a sign extension of the significant value, but we were previously only validating that unsigned LEBs had their unused bytes set to zero. Re-enable the spec test that checks for proper validation.
1 parent eceb0fb commit 3acacac

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

scripts/test/shared.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@ def get_tests(test_dir, extensions=[], recursive=False):
400400
# expected-output/ if any.
401401
SPEC_TESTS_TO_SKIP = [
402402
# Malformed module accepted
403-
'binary-leb128.wast',
404403
'utf8-custom-section-id.wast',
405404
'utf8-import-field.wast',
406405
'utf8-import-module.wast',

src/wasm-binary.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,22 @@ template<typename T, typename MiniT> struct LEB {
102102
bool last = !(byte & 128);
103103
T payload = byte & 127;
104104
using mask_type = typename std::make_unsigned<T>::type;
105-
auto shift_mask = 0 == shift
106-
? ~mask_type(0)
107-
: ((mask_type(1) << (sizeof(T) * 8 - shift)) - 1u);
108-
T significant_payload = payload & shift_mask;
109-
if (significant_payload != payload) {
110-
if (!(std::is_signed<T>::value && last)) {
111-
throw ParseException("LEB dropped bits only valid for signed LEB");
105+
auto payload_mask = 0 == shift
106+
? ~mask_type(0)
107+
: ((mask_type(1) << (sizeof(T) * 8 - shift)) - 1u);
108+
T significant_payload = payload_mask & payload;
109+
value |= significant_payload << shift;
110+
T unused_bits_mask = ~payload_mask & 127;
111+
T unused_bits = payload & unused_bits_mask;
112+
if (std::is_signed_v<T> && value < 0) {
113+
if (unused_bits != unused_bits_mask) {
114+
throw ParseException("Unused negative LEB bits must be 1s");
115+
}
116+
} else {
117+
if (unused_bits != 0) {
118+
throw ParseException("Unused non-negative LEB bits must be 0s");
112119
}
113120
}
114-
value |= significant_payload << shift;
115121
if (last) {
116122
break;
117123
}
@@ -120,9 +126,8 @@ template<typename T, typename MiniT> struct LEB {
120126
throw ParseException("LEB overflow");
121127
}
122128
}
123-
// If signed LEB, then we might need to sign-extend. (compile should
124-
// optimize this out if not needed).
125-
if (std::is_signed<T>::value) {
129+
// If signed LEB, then we might need to sign-extend.
130+
if constexpr (std::is_signed_v<T>) {
126131
shift += 7;
127132
if ((byte & 64) && size_t(shift) < 8 * sizeof(T)) {
128133
size_t sext_bits = 8 * sizeof(T) - size_t(shift);

0 commit comments

Comments
 (0)