diff --git a/planus/src/table_reader.rs b/planus/src/table_reader.rs index 7b54ad73..6a9b1714 100644 --- a/planus/src/table_reader.rs +++ b/planus/src/table_reader.rs @@ -101,21 +101,23 @@ impl<'buf> Table<'buf> { error_kind, }; - let offset = self - .vtable - .get(2 * vtable_offset..2 * (vtable_offset + 2)) - .ok_or_else(|| make_error(ErrorKind::InvalidOffset))?; - - let tag_offset = u16::from_le_bytes(offset[..2].try_into().unwrap()) as usize; - let value_offset = u16::from_le_bytes(offset[2..].try_into().unwrap()) as usize; - - let tag = u8::from_buffer(self.object, tag_offset).map_err(make_error)?; - if tag_offset != 0 && value_offset != 0 && tag != 0 { - T::from_buffer(self.object, value_offset, tag) - .map(Some) - .map_err(make_error) - } else { + if let Some(offset) = self.vtable.get(2 * vtable_offset..2 * (vtable_offset + 2)) { + let tag_offset = u16::from_le_bytes(offset[..2].try_into().unwrap()) as usize; + let value_offset = u16::from_le_bytes(offset[2..].try_into().unwrap()) as usize; + let tag = u8::from_buffer(self.object, tag_offset).map_err(make_error)?; + if tag_offset != 0 && value_offset != 0 && tag != 0 { + T::from_buffer(self.object, value_offset, tag) + .map(Some) + .map_err(make_error) + } else { + Ok(None) + } + } else if self.vtable.len() <= 2 * vtable_offset { Ok(None) + } else { + Err(make_error(ErrorKind::InvalidVtableLength { + length: self.vtable.len() as u16 + 4, + })) } } diff --git a/test/rust/test_files/issue_99.fbs b/test/rust/test_files/issue_99.fbs new file mode 100644 index 00000000..5e40c2b4 --- /dev/null +++ b/test/rust/test_files/issue_99.fbs @@ -0,0 +1,9 @@ +table Table {} + +union Union { + t: Table +} + +table Root { + f: Union; +} diff --git a/test/rust/test_files/issue_99/deserialize/bad-file.bin b/test/rust/test_files/issue_99/deserialize/bad-file.bin new file mode 100644 index 00000000..826e9878 Binary files /dev/null and b/test/rust/test_files/issue_99/deserialize/bad-file.bin differ diff --git a/test/rust/test_files/issue_99/deserialize/bad-file.txt b/test/rust/test_files/issue_99/deserialize/bad-file.txt new file mode 100644 index 00000000..8ec31015 --- /dev/null +++ b/test/rust/test_files/issue_99/deserialize/bad-file.txt @@ -0,0 +1,14 @@ +RootRef { + f: Err( + Error { + source_location: ErrorLocation { + type_: "Root", + method: "f", + byte_offset: 10, + }, + error_kind: InvalidVtableLength { + length: 6, + }, + }, + ), +} \ No newline at end of file diff --git a/test/rust/test_files/issue_99/deserialize/issue-99.bin b/test/rust/test_files/issue_99/deserialize/issue-99.bin new file mode 100644 index 00000000..e07cbd44 Binary files /dev/null and b/test/rust/test_files/issue_99/deserialize/issue-99.bin differ diff --git a/test/rust/test_files/issue_99/deserialize/issue-99.txt b/test/rust/test_files/issue_99/deserialize/issue-99.txt new file mode 100644 index 00000000..a9655539 --- /dev/null +++ b/test/rust/test_files/issue_99/deserialize/issue-99.txt @@ -0,0 +1 @@ +RootRef \ No newline at end of file diff --git a/test/rust/test_files/issue_99/serialize/non_null.bin b/test/rust/test_files/issue_99/serialize/non_null.bin new file mode 100644 index 00000000..76f90204 Binary files /dev/null and b/test/rust/test_files/issue_99/serialize/non_null.bin differ diff --git a/test/rust/test_files/issue_99/serialize/non_null.dbg.txt b/test/rust/test_files/issue_99/serialize/non_null.dbg.txt new file mode 100644 index 00000000..b4c3e52b --- /dev/null +++ b/test/rust/test_files/issue_99/serialize/non_null.dbg.txt @@ -0,0 +1,4 @@ +Root { + f_type: t, + f: Table, +} \ No newline at end of file diff --git a/test/rust/test_files/issue_99/serialize/non_null.dump.txt b/test/rust/test_files/issue_99/serialize/non_null.dump.txt new file mode 100644 index 00000000..e79e82c5 --- /dev/null +++ b/test/rust/test_files/issue_99/serialize/non_null.dump.txt @@ -0,0 +1,6 @@ +obj @ 0x04..0x0d +vtable @ 0x10..0x18 +field[0] @ 0x0c..0x0d: + 01 +field[1] @ 0x08..0x0c: + 10 00 00 00 diff --git a/test/rust/test_files/issue_99/serialize/non_null.json b/test/rust/test_files/issue_99/serialize/non_null.json new file mode 100644 index 00000000..ee786477 --- /dev/null +++ b/test/rust/test_files/issue_99/serialize/non_null.json @@ -0,0 +1 @@ +{"f": {"T": {}}} diff --git a/test/rust/test_files/issue_99/serialize/null.bin b/test/rust/test_files/issue_99/serialize/null.bin new file mode 100644 index 00000000..080d01d9 Binary files /dev/null and b/test/rust/test_files/issue_99/serialize/null.bin differ diff --git a/test/rust/test_files/issue_99/serialize/null.dbg.txt b/test/rust/test_files/issue_99/serialize/null.dbg.txt new file mode 100644 index 00000000..358684f0 --- /dev/null +++ b/test/rust/test_files/issue_99/serialize/null.dbg.txt @@ -0,0 +1,4 @@ +Root { + f_type: NONE, + f: None, +} \ No newline at end of file diff --git a/test/rust/test_files/issue_99/serialize/null.dump.txt b/test/rust/test_files/issue_99/serialize/null.dump.txt new file mode 100644 index 00000000..94cbf97b --- /dev/null +++ b/test/rust/test_files/issue_99/serialize/null.dump.txt @@ -0,0 +1,2 @@ +obj @ 0x04..0x08 +vtable @ 0x08..0x0c diff --git a/test/rust/test_files/issue_99/serialize/null.json b/test/rust/test_files/issue_99/serialize/null.json new file mode 100644 index 00000000..b21790b2 --- /dev/null +++ b/test/rust/test_files/issue_99/serialize/null.json @@ -0,0 +1 @@ +{"f": null}