diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2021-03-12 17:58:58 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2021-03-12 17:58:58 +0300 |
commit | bcac17196a90967b78013aefd89bf547cf8e694c (patch) | |
tree | 989f271aefd12e428e948b9e7996231dc943d599 /source/blender/blenloader/intern | |
parent | f0c3ec3dc8bc0e361b47952bad105499a2d23fae (diff) |
Fix heap buffer overflow appending/linking from a blend file
Add new function `blo_bhead_is_id_valid_type()` to correctly check the
blend file block type.
File block type codes have four bytes, and two of those are only in use
when these blocks contain ID datablocks (like `"OB\0\0"`). However,
there are other types defined in `BLO_blend_defs.h` that have four
bytes, like `TEST`, `ENDB`, etc.
The function `BKE_idtype_idcode_is_valid(short idcode)` was used to
check for ID datablocks while reading a blend file. This only takes a
2-byte parameter, and thus its result is invalid for the 4-byte codes.
For `TEST` blocks, it would actually consider it a `TE` block, which is
a valid identifier for a Texture. This caused the heap buffer overflow,
as the datablock is not a valid ID, and thus the bytes that were
expected to form an ID name actually encode something completely
different.
Reviewed By: mont29
Differential Revision: https://developer.blender.org/D10703
Diffstat (limited to 'source/blender/blenloader/intern')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 302abf35f1c..e809b22cdbf 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -555,6 +555,23 @@ static void read_file_version(FileData *fd, Main *main) } } +static bool blo_bhead_is_id(BHead *bhead) +{ + /* BHead codes are four bytes (like 'ENDB', 'TEST', etc.), but if the two most-significant bytes + * are zero, the values actually indicate an ID type. */ + return bhead->code <= 0xFFFF; +} + +static bool blo_bhead_is_id_valid_type(BHead *bhead) +{ + if (!blo_bhead_is_id(bhead)) { + return false; + } + + const short id_type_code = bhead->code & 0xFFFF; + return BKE_idtype_idcode_is_valid(id_type_code); +} + #ifdef USE_GHASH_BHEAD static void read_file_bhead_idname_map_create(FileData *fd) { @@ -568,8 +585,9 @@ static void read_file_bhead_idname_map_create(FileData *fd) for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) { if (code_prev != bhead->code) { code_prev = bhead->code; - is_link = BKE_idtype_idcode_is_valid(code_prev) ? BKE_idtype_idcode_is_linkable(code_prev) : - false; + is_link = blo_bhead_is_id_valid_type(bhead) ? + BKE_idtype_idcode_is_linkable((short)code_prev) : + false; } if (is_link) { @@ -584,8 +602,9 @@ static void read_file_bhead_idname_map_create(FileData *fd) for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) { if (code_prev != bhead->code) { code_prev = bhead->code; - is_link = BKE_idtype_idcode_is_valid(code_prev) ? BKE_idtype_idcode_is_linkable(code_prev) : - false; + is_link = blo_bhead_is_id_valid_type(bhead) ? + BKE_idtype_idcode_is_linkable((short)code_prev) : + false; } if (is_link) { @@ -973,7 +992,7 @@ const char *blo_bhead_id_name(const FileData *fd, const BHead *bhead) /* Warning! Caller's responsibility to ensure given bhead **is** an ID one! */ AssetMetaData *blo_bhead_id_asset_data_address(const FileData *fd, const BHead *bhead) { - BLI_assert(BKE_idtype_idcode_is_valid(bhead->code)); + BLI_assert(blo_bhead_is_id_valid_type(bhead)); return (fd->id_asset_data_offset >= 0) ? *(AssetMetaData **)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_asset_data_offset) : NULL; @@ -3711,7 +3730,7 @@ static BHead *read_libblock(FileData *fd, BHead *blo_read_asset_data_block(FileData *fd, BHead *bhead, AssetMetaData **r_asset_data) { - BLI_assert(BKE_idtype_idcode_is_valid(bhead->code)); + BLI_assert(blo_bhead_is_id_valid_type(bhead)); bhead = read_data_into_datamap(fd, bhead, "asset-data read"); @@ -4923,7 +4942,7 @@ int BLO_library_link_copypaste(Main *mainl, BlendHandle *bh, const uint64_t id_t break; } - if (BKE_idtype_idcode_is_valid(bhead->code) && BKE_idtype_idcode_is_linkable(bhead->code) && + if (blo_bhead_is_id_valid_type(bhead) && BKE_idtype_idcode_is_linkable((short)bhead->code) && (id_types_mask == 0 || (BKE_idtype_idcode_to_idfilter((short)bhead->code) & id_types_mask) != 0)) { read_libblock(fd, mainl, bhead, LIB_TAG_NEED_EXPAND | LIB_TAG_INDIRECT, false, &id); |