summaryrefslogtreecommitdiff
path: root/libbindgen/src
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-12-02 17:14:37 -0800
committerGitHub <noreply@github.com>2016-12-02 17:14:37 -0800
commit8013e0c7bc28e0883363649c94360b4878d1d742 (patch)
treee9f0d78f6fde2b58cf6f75e191160f773d8d4396 /libbindgen/src
parent18711e0fc7dd2500df524a7c9f9db4864a8f0c38 (diff)
parentfa5ad81713a738dd181333de3f60a432f22a5003 (diff)
Auto merge of #314 - fitzgen:assert-no-infinite-loops-in-ancestors, r=emilio
Assert that we won't infinite loop 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.
Diffstat (limited to 'libbindgen/src')
-rw-r--r--libbindgen/src/ir/item.rs48
1 files changed, 44 insertions, 4 deletions
diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs
index 76ab0d55..f12e4b54 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 DebugOnlyItemSet = ItemSet;
+ } else {
+ struct DebugOnlyItemSet;
+
+ impl DebugOnlyItemSet {
+ fn new() -> Self {
+ DebugOnlyItemSet
+ }
+
+ 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: DebugOnlyItemSet,
+}
+
+impl <'a, 'b> ItemAncestorsIter<'a, 'b>
+ where 'b: 'a
+{
+ fn new(ctx: &'a BindgenContext<'b>, item: ItemId) -> Self {
+ ItemAncestorsIter {
+ item: item,
+ ctx: ctx,
+ seen: DebugOnlyItemSet::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)
}
}
@@ -553,8 +588,13 @@ impl Item {
ctx: &BindgenContext,
for_name_checking: bool)
-> ItemId {
+ let mut targets_seen = DebugOnlyItemSet::new();
let mut item = self;
+
loop {
+ debug_assert!(!targets_seen.contains(&item.id()));
+ targets_seen.insert(item.id());
+
match *item.kind() {
ItemKind::Type(ref ty) => {
match *ty.kind() {