290 static int
291 _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
292 int unique, int noval, int *changed)
293 {
when considering range: -128 <= value <= 1
taking False path
294 int i, cmp;
295 KEY_TYPE key;
296
297 /* Subtle: there may or may not be a value. If there is, we need to
298 * check its type early, so that in case of error we can get out before
299 * mutating the bucket. But because value isn't used on all paths, if
300 * we don't initialize value then gcc gives a nuisance complaint that
301 * value may be used initialized (it can't be, but gcc doesn't know
302 * that). So we initialize it. However, VALUE_TYPE can be various types,
303 * including int, PyObject*, and char[6], so it's a puzzle to spell
304 * initialization. It so happens that {0} is a valid initializer for all
305 * these types.
306 */
307 VALUE_TYPE value = {0}; /* squash nuisance warning */
308 int result = -1; /* until proven innocent */
309 int copied = 1;
310
311 COPY_KEY_FROM_ARG(key, keyarg, copied);
312 UNLESS(copied) return -1;
taking False path
313
314 /* Copy the value early (if needed), so that in case of error a
315 * pile of bucket mutations don't need to be undone.
316 */
317 if (v && !noval) {
when considering range: -0x80000000 <= value <= -1
taking False path
318 COPY_VALUE_FROM_ARG(value, v, copied);
319 UNLESS(copied) return -1;
320 }
321
322 UNLESS (PER_USE(self)) return -1;
when considering range: -128 <= value <= -2
taking True path
when considering range: -128 <= value <= -1
taking False path
taking False path
323
324 BUCKET_SEARCH(i, cmp, self, key, goto Done);
when considering range: -0x80000000 <= _hi <= 0
taking False path
325 if (cmp == 0) {
taking False path
326 /* The key exists, at index i. */
327
328 if (v) {
329 /* The key exists at index i, and there's a new value.
330 * If unique, we're not supposed to replace it. If noval, or this
331 * is a set bucket (self->values is NULL), there's nothing to do.
332 */
333 if (unique || noval || self->values == NULL) {
334 result = 0;
335 goto Done;
336 }
337
338 /* The key exists at index i, and we need to replace the value. */
339 #ifdef VALUE_SAME
340 /* short-circuit if no change */
341 if (VALUE_SAME(self->values[i], value)) {
342 result = 0;
343 goto Done;
344 }
345 #endif
346 if (changed)
347 *changed = 1;
348 DECREF_VALUE(self->values[i]);
349 COPY_VALUE(self->values[i], value);
350 INCREF_VALUE(self->values[i]);
351 if (PER_CHANGED(self) >= 0)
352 result = 0;
353 goto Done;
354 }
355
356 /* The key exists at index i, and should be deleted. */
357 DECREF_KEY(self->keys[i]);
358 self->len--;
359 if (i < self->len)
360 memmove(self->keys + i, self->keys + i+1,
361 sizeof(KEY_TYPE)*(self->len - i));
362
363 if (self->values) {
364 DECREF_VALUE(self->values[i]);
365 if (i < self->len)
366 memmove(self->values + i, self->values + i+1,
367 sizeof(VALUE_TYPE)*(self->len - i));
368 }
369
370 if (! self->len) {
371 self->size = 0;
372 free(self->keys);
373 self->keys = NULL;
374 if (self->values) {
375 free(self->values);
376 self->values = NULL;
377 }
378 }
379
380 if (changed)
381 *changed = 1;
382 if (PER_CHANGED(self) >= 0)
383 result = 1;
384 goto Done;
385 }
386
387 /* The key doesn't exist, and belongs at index i. */
388 if (!v) {
taking False path
389 /* Can't delete a non-existent key. */
390 PyErr_SetObject(PyExc_KeyError, keyarg);
391 goto Done;
392 }
393
394 /* The key doesn't exist and should be inserted at index i. */
395 if (self->len == self->size && Bucket_grow(self, -1, noval) < 0)
when taking True path
when considering range: 0 <= value <= 0x7fffffff
taking False path
396 goto Done;
397
398 if (self->len > i) {
when taking True path
399 memmove(self->keys + i + 1, self->keys + i,
400 sizeof(KEY_TYPE) * (self->len - i));
401 if (self->values) {
when treating unknown struct PyObject * * from src/BTrees/BucketTemplate.c:401 as non-NULL
taking True path
402 memmove(self->values + i + 1, self->values + i,
403 sizeof(VALUE_TYPE) * (self->len - i));
404 }
405 }
406
407 COPY_KEY(self->keys[i], key);
when treating unknown struct PyObject * * from src/BTrees/BucketTemplate.c:407 as non-NULL
'*keyarg' is now referenced by 1 non-stack value(s): heap-region-17
408 INCREF_KEY(self->keys[i]);
when treating unknown struct PyObject * * from src/BTrees/BucketTemplate.c:408 as non-NULL
when treating unknown struct PyObject * from src/BTrees/BucketTemplate.c:408 as non-NULL
409
410 if (! noval) {
taking False path
411 COPY_VALUE(self->values[i], value);
412 INCREF_VALUE(self->values[i]);
413 }
414
415 self->len++;
416 if (changed)
when taking False path
417 *changed = 1;
418 if (PER_CHANGED(self) >= 0)
when treating unknown struct cPersistenceCAPIstruct * from src/persistent/cPersistence.h:112 as non-NULL
calling unknown int (*) (struct cPersistentObject *) from src/BTrees/BucketTemplate.c:418
when considering range: 0 <= value <= 0x7fffffff
taking True path
419 result = 1;
420
421 Done:
422 PER_UNUSE(self);
calling unknown void (*) (struct cPersistentObject *) from src/BTrees/BucketTemplate.c:422
423 return result;
424 }
ob_refcnt of '*keyarg' is 1 too low
was expecting final ob_refcnt to be N + 1 (for some unknown N)
due to object being referenced by: heap-region-17
but final ob_refcnt is N + 0
found 10 similar trace(s) to this