boot: allow BCD fields to end at buffer limit

Allow offset + len == max; the range ends exactly at the buffer boundary.

Keep the overflow-safe bounds check and cover the edge case in test-bcd.

Follow-up for: aa1d0f2587.
This commit is contained in:
dongshengyuan
2026-07-14 18:52:04 +08:00
parent 4e67935b77
commit 231857cfe8
2 changed files with 18 additions and 7 deletions
+9 -7
View File
@@ -93,15 +93,17 @@ assert_cc(offsetof(KeyValue, data_offset) == 8);
assert_cc(offsetof(KeyValue, data_type) == 12);
assert_cc(offsetof(KeyValue, name) == 20);
#define BAD_OFFSET(offset, len, max) \
((uint64_t) (offset) + (len) >= (max))
static bool bad_offset(uint64_t offset, uint64_t len, uint64_t max) {
return offset > max || len > max - offset;
}
#define BAD_STRUCT(type, offset, max) \
((uint64_t) (offset) + sizeof(type) >= (max))
bad_offset(offset, sizeof(type), max)
#define BAD_ARRAY(type, array, offset, array_len, max) \
((uint64_t) (offset) + offsetof(type, array) + \
sizeof((type){}.array[0]) * (uint64_t) (array_len) >= (max))
bad_offset(offset, \
offsetof(type, array) + sizeof((type){}.array[0]) * (uint64_t) (array_len), \
max)
static const Key *get_key(const uint8_t *bcd, uint32_t bcd_len, uint32_t offset, const char *name);
@@ -167,7 +169,7 @@ static const KeyValue *get_key_value(const uint8_t *bcd, uint32_t bcd_len, const
if (key->n_key_values == 0)
return NULL;
if (BAD_OFFSET(key->key_values_offset, sizeof(uint32_t) * (uint64_t) key->n_key_values, bcd_len) ||
if (bad_offset(key->key_values_offset, sizeof(uint32_t) * (uint64_t) key->n_key_values, bcd_len) ||
(uintptr_t) (bcd + key->key_values_offset) % alignof(uint32_t) != 0)
return NULL;
@@ -191,7 +193,7 @@ static const KeyValue *get_key_value(const uint8_t *bcd, uint32_t bcd_len, const
if (FLAGS_SET(kv->data_size, UINT32_C(1) << 31))
continue;
if (BAD_OFFSET(kv->data_offset, kv->data_size, bcd_len))
if (bad_offset(kv->data_offset, kv->data_size, bcd_len))
continue;
if (strncaseeq8(name, kv->name, kv->name_len) && strlen8(name) == kv->name_len)
+9
View File
@@ -90,6 +90,15 @@ TEST(base_block) {
*bcd = backup;
}
TEST(offset_bounds) {
assert_se(!bad_offset(0, sizeof(Key), sizeof(Key)));
assert_se(!BAD_STRUCT(Key, 0, sizeof(Key)));
assert_se(!BAD_ARRAY(Key, key_name, 0, 0, sizeof(Key)));
assert_se(bad_offset(0, sizeof(Key) + 1, sizeof(Key)));
assert_se(bad_offset(UINT32_MAX, 2, UINT32_MAX));
}
TEST(bad_bcd) {
size_t len;
uint8_t *hbins;