Commit a88c74ba authored by Kevin Modzelewski's avatar Kevin Modzelewski

Be more careful about how we remove elements from sets

ie if we do set.remove(k), we don't decrement k -- we decrement
whatever was in the set, which can be different.
parent a48acf8c
...@@ -102,10 +102,14 @@ static void _setAdd(BoxedSet* self, BoxAndHash val) { ...@@ -102,10 +102,14 @@ static void _setAdd(BoxedSet* self, BoxAndHash val) {
_setAddStolen(self, val); _setAddStolen(self, val);
} }
static void _setRemove(BoxedSet* self, BoxAndHash val) { static bool _setRemove(BoxedSet* self, BoxAndHash val) {
bool erased = self->s.erase(val); auto it = self->s.find(val);
if (erased) if (it == self->s.end())
Py_DECREF(val.value); return false;
Box* to_decref = it->value;
self->s.erase(it);
Py_DECREF(to_decref);
return true;
} }
// Creates a set of type 'cls' from 'container' (NULL to get an empty set). // Creates a set of type 'cls' from 'container' (NULL to get an empty set).
...@@ -288,8 +292,7 @@ static void _setSymmetricDifferenceUpdate(BoxedSet* self, Box* other) { ...@@ -288,8 +292,7 @@ static void _setSymmetricDifferenceUpdate(BoxedSet* self, Box* other) {
for (auto elt : other_set->s) { for (auto elt : other_set->s) {
auto&& p = self->s.insert(elt); auto&& p = self->s.insert(elt);
if (!p.second /* already exists */) { if (!p.second /* already exists */) {
self->s.erase(p.first); _setRemove(self, elt);
Py_DECREF(elt.value);
} else { } else {
Py_INCREF(elt.value); Py_INCREF(elt.value);
} }
...@@ -364,9 +367,7 @@ Box* setISub(BoxedSet* lhs, BoxedSet* rhs) { ...@@ -364,9 +367,7 @@ Box* setISub(BoxedSet* lhs, BoxedSet* rhs) {
// TODO: write and call setDifferenceUpdate2 // TODO: write and call setDifferenceUpdate2
for (auto&& elt : rhs->s) { for (auto&& elt : rhs->s) {
bool found = lhs->s.erase(elt); _setRemove(lhs, elt);
if (found)
Py_DECREF(elt.value);
} }
return incref(lhs); return incref(lhs);
} }
...@@ -734,12 +735,9 @@ Box* setRemove(BoxedSet* self, Box* key) { ...@@ -734,12 +735,9 @@ Box* setRemove(BoxedSet* self, Box* key) {
if (PySet_Check(key)) { if (PySet_Check(key)) {
try { try {
BoxAndHash k_hash(key); bool existed = _setRemove(self, key);
if (self->s.find(k_hash) != self->s.end()) { if (existed)
bool existed = self->s.erase(k_hash); return incref(None);
if (existed)
return incref(None);
}
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(TypeError)) if (!e.matches(TypeError))
throw e; throw e;
...@@ -748,23 +746,17 @@ Box* setRemove(BoxedSet* self, Box* key) { ...@@ -748,23 +746,17 @@ Box* setRemove(BoxedSet* self, Box* key) {
BoxedSet* tmpKey = makeNewSet(frozenset_cls, key); BoxedSet* tmpKey = makeNewSet(frozenset_cls, key);
AUTO_DECREF(tmpKey); AUTO_DECREF(tmpKey);
if (self->s.find(tmpKey) != self->s.end()) { bool existed = _setRemove(self, tmpKey);
bool existed = self->s.erase(tmpKey); if (existed)
if (existed) return incref(None);
return incref(None);
}
} }
raiseExcHelper(KeyError, key); raiseExcHelper(KeyError, key);
} }
auto it = self->s.find(key); bool existed = _setRemove(self, key);
if (it == self->s.end()) { if (existed)
raiseExcHelper(KeyError, key); return incref(None);
} raiseExcHelper(KeyError, key);
self->s.erase(it);
Py_DECREF(key);
return incref(None);
} }
Box* setDiscard(BoxedSet* self, Box* key) { Box* setDiscard(BoxedSet* self, Box* key) {
...@@ -772,10 +764,7 @@ Box* setDiscard(BoxedSet* self, Box* key) { ...@@ -772,10 +764,7 @@ Box* setDiscard(BoxedSet* self, Box* key) {
if (PySet_Check(key)) { if (PySet_Check(key)) {
try { try {
BoxAndHash k_hash(key); _setRemove(self, key);
if (self->s.find(k_hash) != self->s.end()) {
self->s.erase(k_hash);
}
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(TypeError)) if (!e.matches(TypeError))
throw e; throw e;
...@@ -784,18 +773,12 @@ Box* setDiscard(BoxedSet* self, Box* key) { ...@@ -784,18 +773,12 @@ Box* setDiscard(BoxedSet* self, Box* key) {
BoxedSet* tmpKey = makeNewSet(frozenset_cls, key); BoxedSet* tmpKey = makeNewSet(frozenset_cls, key);
AUTO_DECREF(tmpKey); AUTO_DECREF(tmpKey);
if (self->s.find(tmpKey) != self->s.end()) { _setRemove(self, tmpKey);
self->s.erase(tmpKey);
}
} }
return incref(None); return incref(None);
} }
auto it = self->s.find(key); _setRemove(self, key);
if (it != self->s.end()) {
self->s.erase(it);
Py_DECREF(key);
}
return incref(None); return incref(None);
} }
......
...@@ -235,3 +235,8 @@ print sorted(l) ...@@ -235,3 +235,8 @@ print sorted(l)
d = dict() d = dict()
d['two'] = d d['two'] = d
print d print d
# Remove an item using a different key:
d = {1:1}
d.pop(1L)
# expected: reffail
s1 = {1} s1 = {1}
def sorted(s): def sorted(s):
...@@ -251,3 +250,13 @@ a = set() ...@@ -251,3 +250,13 @@ a = set()
a.add(foo) a.add(foo)
print(a.remove(foo)) print(a.remove(foo))
print(foo in set()) print(foo in set())
# Remove an item using a different key:
s = set()
s.add(1)
s.remove(1L)
s = set([1, 2, 3, 4])
s2 = set([3L, 4L, 5L, 6L])
s.symmetric_difference_update(s2)
# expected: reffail
import urlparse import urlparse
print urlparse.urlparse("http://www.dropbox.com") print urlparse.urlparse("http://www.dropbox.com")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment