/
githubmirror
/
libcbor
Обзор
Документация
Войти
/
githubmirror
/
libcbor
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/cbor/arrays.c
136 строк
4 KB
Pavel Kalvoda
Add bounds check in cbor_array_get() (#388)
08 фев 2026, 20:19
Не верифицирован
08 фев 2026, 20:19
5b0e20c
Код
Авторство
О чём код?
/* * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> * * libcbor is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include <stdbool.h> #include "arrays.h" #include "internal/memory_utils.h" size_t cbor_array_size(const cbor_item_t* item) { CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.end_ptr; } size_t cbor_array_allocated(const cbor_item_t* item) { CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.allocated; } cbor_item_t* cbor_array_get(const cbor_item_t* item, size_t index) { CBOR_ASSERT(cbor_isa_array(item)); if (index >= item->metadata.array_metadata.end_ptr) { return NULL; } return cbor_incref(((cbor_item_t**)item->data)[index]); } bool cbor_array_set(cbor_item_t* item, size_t index, cbor_item_t* value) { if (index == item->metadata.array_metadata.end_ptr) { return cbor_array_push(item, value); } else if (index < item->metadata.array_metadata.end_ptr) { return cbor_array_replace(item, index, value); } else { return false; } } bool cbor_array_replace(cbor_item_t* item, size_t index, cbor_item_t* value) { if (index >= item->metadata.array_metadata.end_ptr) return false; /* We cannot use cbor_array_get as that would increase the refcount */ cbor_intermediate_decref(((cbor_item_t**)item->data)[index]); ((cbor_item_t**)item->data)[index] = cbor_incref(value); return true; } bool cbor_array_push(cbor_item_t* array, cbor_item_t* pushee) { CBOR_ASSERT(cbor_isa_array(array)); struct _cbor_array_metadata* metadata = (struct _cbor_array_metadata*)&array->metadata; cbor_item_t** data = (cbor_item_t**)array->data; if (cbor_array_is_definite(array)) { /* Do not reallocate definite arrays */ if (metadata->end_ptr >= metadata->allocated) { return false; } data[metadata->end_ptr++] = pushee; } else { /* Exponential realloc */ if (metadata->end_ptr >= metadata->allocated) { // Check for overflows first if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) { return false; } size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated; unsigned char* new_data = _cbor_realloc_multiple( array->data, sizeof(cbor_item_t*), new_allocation); if (new_data == NULL) { return false; } array->data = new_data; metadata->allocated = new_allocation; } ((cbor_item_t**)array->data)[metadata->end_ptr++] = pushee; } cbor_incref(pushee); return true; } bool cbor_array_is_definite(const cbor_item_t* item) { CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE; } bool cbor_array_is_indefinite(const cbor_item_t* item) { CBOR_ASSERT(cbor_isa_array(item)); return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE; } cbor_item_t** cbor_array_handle(const cbor_item_t* item) { CBOR_ASSERT(cbor_isa_array(item)); return (cbor_item_t**)item->data; } cbor_item_t* cbor_new_definite_array(size_t size) { cbor_item_t* item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); cbor_item_t** data = _cbor_alloc_multiple(sizeof(cbor_item_t*), size); _CBOR_DEPENDENT_NOTNULL(item, data); for (size_t i = 0; i < size; i++) { data[i] = NULL; } *item = (cbor_item_t){ .refcount = 1, .type = CBOR_TYPE_ARRAY, .metadata = {.array_metadata = {.type = _CBOR_METADATA_DEFINITE, .allocated = size, .end_ptr = 0}}, .data = (unsigned char*)data}; return item; } cbor_item_t* cbor_new_indefinite_array(void) { cbor_item_t* item = _cbor_malloc(sizeof(cbor_item_t)); _CBOR_NOTNULL(item); *item = (cbor_item_t){ .refcount = 1, .type = CBOR_TYPE_ARRAY, .metadata = {.array_metadata = {.type = _CBOR_METADATA_INDEFINITE, .allocated = 0, .end_ptr = 0}}, .data = NULL /* Can be safely realloc-ed */ }; return item; }