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(¤tbucket, 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