Skip to content

Commit 950a2ba

Browse files
committed
fix bug where get_named() could panic on non-existent fields
1 parent 166f7eb commit 950a2ba

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

capnp/src/schema.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,19 @@ impl StructSchema {
6060
let fields = self.get_fields()?;
6161
let mut lower: usize = 0;
6262
let mut upper: usize = self.raw.generic.members_by_name.len();
63-
let mut mid: usize = (lower + upper) / 2;
64-
let mut candidate_index = self.raw.generic.members_by_name[mid];
65-
let mut candidate_name = fields.get(candidate_index).get_proto().get_name()?;
6663

6764
while lower < upper {
65+
let mid: usize = (lower + upper) / 2;
66+
let candidate_index = self.raw.generic.members_by_name[mid];
67+
let candidate_name = fields.get(candidate_index).get_proto().get_name()?;
68+
6869
use core::cmp::Ordering;
6970
match (&name).partial_cmp(&candidate_name) {
7071
Some(Ordering::Equal) => return Ok(Some(fields.get(candidate_index))),
7172
Some(Ordering::Greater) => lower = mid + 1,
7273
Some(Ordering::Less) => upper = mid,
7374
None => unreachable!(),
7475
}
75-
mid = (lower + upper) / 2;
76-
candidate_index = self.raw.generic.members_by_name[mid];
77-
candidate_name = fields.get(candidate_index).get_proto().get_name()?;
7876
}
7977
Ok(None)
8078
}

capnpc/test/dynamic.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,17 @@ fn test_stringify_list_list() {
391391
let stringified = format!("{:?}", root.into_reader());
392392
assert_eq!(stringified, "[[1111, 2222, 3333], [123456]]");
393393
}
394+
395+
#[test]
396+
fn test_get_named_missing() {
397+
let mut builder = message::Builder::new_default();
398+
let root: test_all_types::Builder<'_> = builder.init_root();
399+
let root: dynamic_value::Builder<'_> = root.into();
400+
let mut root: dynamic_struct::Builder<'_> = root.downcast();
401+
test_util::dynamic_init_test_message(root.reborrow());
402+
let root = root.into_reader();
403+
// try a bunch of fields that don't exist
404+
assert!(root.get_named("AAAAAAA").is_err());
405+
assert!(root.get_named("abcdef").is_err());
406+
assert!(root.get_named("zzzzzzz").is_err());
407+
}

0 commit comments

Comments
 (0)