diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2016-12-02 14:38:27 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2016-12-02 14:38:27 -0800 |
commit | 12ee656be8dbacb49179060763830c08a5202156 (patch) | |
tree | 519da16633f6d060ed50879b55aab134ad44d7fb | |
parent | 2c43aaef40ca43ed7be52ea738065bfbe3baae6c (diff) |
Assert that we won't infinite loop in ItemAncestorsIter
In non-release builds with debug assertions, keep track of the set of
`ItemId`s that we have iterated over in `ItemAncestorsIter` and make
sure that we don't reach an ancestor we have already yielded, which
would trigger an infinite loop.
-rw-r--r-- | libbindgen/src/ir/item.rs | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index 76ab0d55..f4272e2d 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -55,12 +55,45 @@ pub trait ItemAncestors { -> ItemAncestorsIter<'a, 'b>; } +cfg_if! { + if #[cfg(debug_assertions)] { + type AncestorsSeen = ItemSet; + } else { + struct AncestorsSeen; + + impl AncestorsSeen { + fn new() -> Self { + AncestorsSeen + } + + fn contains(&self,_id: &ItemId) -> bool { + false + } + + fn insert(&mut self, _id: ItemId) {} + } + } +} + /// An iterator over an item and its ancestors. pub struct ItemAncestorsIter<'a, 'b> where 'b: 'a, { item: ItemId, ctx: &'a BindgenContext<'b>, + seen: AncestorsSeen, +} + +impl <'a, 'b> ItemAncestorsIter<'a, 'b> + where 'b: 'a +{ + fn new(ctx: &'a BindgenContext<'b>, item: ItemId) -> Self { + ItemAncestorsIter { + item: item, + ctx: ctx, + seen: AncestorsSeen::new(), + } + } } impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> @@ -70,10 +103,15 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> fn next(&mut self) -> Option<Self::Item> { let item = self.ctx.resolve_item(self.item); + if item.parent_id() == self.item { None } else { self.item = item.parent_id(); + + debug_assert!(!self.seen.contains(&item.id())); + self.seen.insert(item.id()); + Some(item.id()) } } @@ -100,10 +138,7 @@ impl ItemAncestors for ItemId { fn ancestors<'a, 'b>(&self, ctx: &'a BindgenContext<'b>) -> ItemAncestorsIter<'a, 'b> { - ItemAncestorsIter { - item: *self, - ctx: ctx, - } + ItemAncestorsIter::new(ctx, *self) } } |