File: src/BTrees/BTreeItemsTemplate.c
Function: BTreeItems_seek
Error: ob_refcnt of new ref from (unknown) IndexError is 1 too high
134 static int
135 BTreeItems_seek(BTreeItems *self, Py_ssize_t i)
136 {
137     int delta, pseudoindex, currentoffset;
138     Bucket *b, *currentbucket;
139     int error;
140 
141     pseudoindex = self->pseudoindex;
142     currentoffset = self->currentoffset;
143     currentbucket = self->currentbucket;
144     if (currentbucket == NULL) goto no_match;
when treating unknown struct Bucket * from src/BTrees/BTreeItemsTemplate.c:143 as non-NULL
taking False path
145 
146     delta = i - pseudoindex;
147     while (delta > 0) {         /* move right */
when considering range: -0x80000000 <= value <= 0
taking False path
148         int max;
149         /* Want to move right delta positions; the most we can move right in
150          * this bucket is currentbucket->len - currentoffset - 1 positions.
151          */
152         PER_USE_OR_RETURN(currentbucket, -1);
153         max = currentbucket->len - currentoffset - 1;
154         b = currentbucket->next;
155         PER_UNUSE(currentbucket);
156         if (delta <= max) {
157             currentoffset += delta;
158             pseudoindex += delta;
159             if (currentbucket == self->lastbucket
160                 && currentoffset > self->last) goto no_match;
161             break;
162         }
163         /* Move to start of next bucket. */
164         if (currentbucket == self->lastbucket || b == NULL) goto no_match;
165         currentbucket = b;
166         pseudoindex += max + 1;
167         delta -= max + 1;
168         currentoffset = 0;
169     }
170     while (delta < 0) {         /* move left */
when considering range: -0x80000000 <= value <= -1
taking True path
171         int status;
172         /* Want to move left -delta positions; the most we can move left in
173          * this bucket is currentoffset positions.
174          */
175         if ((-delta) <= currentoffset) {
when taking True path
176             currentoffset += delta;
177             pseudoindex += delta;
178             if (currentbucket == self->firstbucket
when taking True path
179                 && currentoffset < self->first) goto no_match;
when taking True path
180             break;
181         }
182         /* Move to end of previous bucket. */
183         if (currentbucket == self->firstbucket) goto no_match;
184         status = PreviousBucket(&currentbucket, self->firstbucket);
185         if (status == 0)
186             goto no_match;
187         else if (status < 0)
188             return -1;
189         pseudoindex -= currentoffset + 1;
190         delta += currentoffset + 1;
191         PER_USE_OR_RETURN(currentbucket, -1);
192         currentoffset = currentbucket->len - 1;
193         PER_UNUSE(currentbucket);
194     }
195 
196     assert(pseudoindex == i);
197 
198     /* Alas, the user may have mutated the bucket since the last time we
199      * were called, and if they deleted stuff, we may be pointing into
200      * trash memory now.
201      */
202     PER_USE_OR_RETURN(currentbucket, -1);
203     error = currentoffset < 0 || currentoffset >= currentbucket->len;
204     PER_UNUSE(currentbucket);
205     if (error) {
206 	PyErr_SetString(PyExc_RuntimeError,
207 	                "the bucket being iterated changed size");
208 	return -1;
209     }
210 
211     Py_INCREF(currentbucket);
212     Py_DECREF(self->currentbucket);
213     self->currentbucket = currentbucket;
214     self->currentoffset = currentoffset;
215     self->pseudoindex = pseudoindex;
216     return 0;
217 
218 no_match:
219     IndexError(i);
when IndexError() succeeds
new ref from (unknown) IndexError allocated at:     IndexError(i);
ob_refcnt is now refs: 1 + N where N >= 0
220     return -1;
221 }
ob_refcnt of new ref from (unknown) IndexError is 1 too high
was expecting final ob_refcnt to be N + 0 (for some unknown N)
but final ob_refcnt is N + 1