LCOV - code coverage report
Current view: top level - common - mem.c (source / functions) Hit Total Coverage
Test: out.info Lines: 8 132 6.1 %
Date: 2022-01-27 10:43:00 Functions: 2 23 8.7 %

          Line data    Source code
       1             : /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
       2             : /*
       3             :    Copyright (C) 2010 Red Hat, Inc.
       4             : 
       5             :    This library is free software; you can redistribute it and/or
       6             :    modify it under the terms of the GNU Lesser General Public
       7             :    License as published by the Free Software Foundation; either
       8             :    version 2.1 of the License, or (at your option) any later version.
       9             : 
      10             :    This library is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :    Lesser General Public License for more details.
      14             : 
      15             :    You should have received a copy of the GNU Lesser General Public
      16             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      17             : */
      18             : #include <config.h>
      19             : 
      20             : #include "mem.h"
      21             : 
      22             : #include <string.h>
      23             : 
      24             : #ifndef MALLOC_ERROR
      25             : #define MALLOC_ERROR(...) SPICE_STMT_START {    \
      26             :     spice_error(__VA_ARGS__);                   \
      27             :     abort();                                    \
      28             : } SPICE_STMT_END
      29             : #endif
      30             : 
      31           0 : size_t spice_strnlen(const char *str, size_t max_len)
      32             : {
      33           0 :     size_t len = 0;
      34             : 
      35           0 :     while (len < max_len && *str != 0) {
      36           0 :         len++;
      37           0 :         str++;
      38             :     }
      39             : 
      40           0 :     return len;
      41             : }
      42             : 
      43           0 : char *spice_strdup(const char *str)
      44             : {
      45             :     char *copy;
      46             :     size_t len;
      47             : 
      48           0 :     if (str == NULL) {
      49           0 :         return NULL;
      50             :     }
      51             : 
      52           0 :     len = strlen(str) + 1;
      53           0 :     copy = (char *)spice_malloc(len);
      54           0 :     memcpy(copy, str, len);
      55           0 :     return copy;
      56             : }
      57             : 
      58           0 : char *spice_strndup(const char *str, size_t n_bytes)
      59             : {
      60             :     char *copy;
      61             : 
      62           0 :     if (str == NULL) {
      63           0 :         return NULL;
      64             :     }
      65             : 
      66           0 :     copy = (char *)spice_malloc(n_bytes + 1);
      67           0 :     strncpy(copy, str, n_bytes);
      68           0 :     copy[n_bytes] = 0;
      69           0 :     return copy;
      70             : }
      71             : 
      72           0 : void *spice_memdup(const void *mem, size_t n_bytes)
      73             : {
      74             :     void *copy;
      75             : 
      76           0 :     if (mem == NULL) {
      77           0 :         return NULL;
      78             :     }
      79             : 
      80           0 :     copy = spice_malloc(n_bytes);
      81           0 :     memcpy(copy, mem, n_bytes);
      82           0 :     return copy;
      83             : }
      84             : 
      85           3 : void *spice_malloc(size_t n_bytes)
      86             : {
      87             :     void *mem;
      88             : 
      89           3 :     if (SPICE_LIKELY(n_bytes)) {
      90           3 :         mem = malloc(n_bytes);
      91             : 
      92           3 :         if (SPICE_LIKELY(mem != NULL)) {
      93           3 :             return mem;
      94             :         }
      95             : 
      96           0 :         MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
      97             :     }
      98           0 :     return NULL;
      99             : }
     100             : 
     101           0 : void *spice_malloc0(size_t n_bytes)
     102             : {
     103             :     void *mem;
     104             : 
     105           0 :     if (SPICE_LIKELY(n_bytes)) {
     106           0 :         mem = calloc(1, n_bytes);
     107             : 
     108           0 :         if (SPICE_LIKELY(mem != NULL)) {
     109           0 :             return mem;
     110             :         }
     111             : 
     112           0 :         MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
     113             :     }
     114           0 :     return NULL;
     115             : }
     116             : 
     117           0 : void *spice_realloc(void *mem, size_t n_bytes)
     118             : {
     119           0 :     if (SPICE_LIKELY(n_bytes)) {
     120           0 :         mem = realloc(mem, n_bytes);
     121             : 
     122           0 :         if (SPICE_LIKELY(mem != NULL)) {
     123           0 :             return mem;
     124             :         }
     125             : 
     126           0 :         MALLOC_ERROR("unable to allocate %lu bytes", (unsigned long)n_bytes);
     127             :     }
     128             : 
     129           0 :     free(mem);
     130             : 
     131           0 :     return NULL;
     132             : }
     133             : 
     134             : #define SIZE_OVERFLOWS(a,b) (SPICE_UNLIKELY ((a) > SIZE_MAX / (b)))
     135             : 
     136           2 : void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes)
     137             : {
     138           2 :     if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
     139           0 :         MALLOC_ERROR("overflow allocating %lu*%lu bytes",
     140             :                      (unsigned long)n_blocks, (unsigned long)n_block_bytes);
     141             :     }
     142             : 
     143           2 :     return spice_malloc(n_blocks * n_block_bytes);
     144             : }
     145             : 
     146           0 : void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size)
     147             : {
     148             :     size_t size1, size2;
     149           0 :     if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
     150           0 :         MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
     151             :                      (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
     152             :     }
     153           0 :     size1 = n_blocks * n_block_bytes;
     154           0 :     size2 = size1 + extra_size;
     155           0 :     if (size2 < size1) {
     156           0 :         MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
     157             :                      (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
     158             :     }
     159           0 :     return spice_malloc(size2);
     160             : }
     161             : 
     162             : 
     163           0 : void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes)
     164             : {
     165           0 :     if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
     166           0 :         MALLOC_ERROR("spice_malloc0_n: overflow allocating %lu*%lu bytes",
     167             :                      (unsigned long)n_blocks, (unsigned long)n_block_bytes);
     168             :     }
     169             : 
     170           0 :     return spice_malloc0 (n_blocks * n_block_bytes);
     171             : }
     172             : 
     173           0 : void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes)
     174             : {
     175           0 :     if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
     176           0 :         MALLOC_ERROR("spice_realloc_n: overflow allocating %lu*%lu bytes",
     177             :                      (unsigned long)n_blocks, (unsigned long)n_block_bytes);
     178             :     }
     179             : 
     180           0 :     return spice_realloc(mem, n_blocks * n_block_bytes);
     181             : }
     182             : 
     183           0 : SpiceChunks *spice_chunks_new(uint32_t count)
     184             : {
     185             :     SpiceChunks *chunks;
     186             : 
     187           0 :     chunks = (SpiceChunks *)spice_malloc_n_m(count, sizeof(SpiceChunk), sizeof(SpiceChunks));
     188           0 :     chunks->flags = 0;
     189           0 :     chunks->num_chunks = count;
     190             : 
     191           0 :     return chunks;
     192             : }
     193             : 
     194           0 : SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len)
     195             : {
     196             :     SpiceChunks *chunks;
     197             : 
     198           0 :     chunks = spice_chunks_new(1);
     199           0 :     chunks->data_size = chunks->chunk[0].len = len;
     200           0 :     chunks->chunk[0].data = data;
     201           0 :     return chunks;
     202             : }
     203             : 
     204           0 : void spice_chunks_destroy(SpiceChunks *chunks)
     205             : {
     206             :     unsigned int i;
     207             : 
     208           0 :     if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
     209           0 :         for (i = 0; i < chunks->num_chunks; i++) {
     210           0 :             free(chunks->chunk[i].data);
     211             :         }
     212             :     }
     213             : 
     214           0 :     free(chunks);
     215           0 : }
     216             : 
     217           0 : void spice_chunks_linearize(SpiceChunks *chunks)
     218             : {
     219             :     uint8_t *data, *p;
     220             :     unsigned int i;
     221             : 
     222           0 :     if (chunks->num_chunks > 1) {
     223           0 :         data = (uint8_t*)spice_malloc(chunks->data_size);
     224           0 :         for (p = data, i = 0; i < chunks->num_chunks; i++) {
     225           0 :             memcpy(p, chunks->chunk[i].data,
     226           0 :                    chunks->chunk[i].len);
     227           0 :             p += chunks->chunk[i].len;
     228             :         }
     229           0 :         if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
     230           0 :             for (i = 0; i < chunks->num_chunks; i++) {
     231           0 :                 free(chunks->chunk[i].data);
     232             :             }
     233             :         }
     234           0 :         chunks->num_chunks = 1;
     235           0 :         chunks->flags |= SPICE_CHUNKS_FLAGS_FREE;
     236           0 :         chunks->flags &= ~SPICE_CHUNKS_FLAGS_UNSTABLE;
     237           0 :         chunks->chunk[0].data = data;
     238           0 :         chunks->chunk[0].len = chunks->data_size;
     239             :     }
     240           0 : }
     241             : 
     242           0 : void spice_buffer_reserve(SpiceBuffer *buffer, size_t len)
     243             : {
     244           0 :     if ((buffer->capacity - buffer->offset) < len) {
     245           0 :         buffer->capacity += (len + 1024);
     246           0 :         buffer->buffer = (uint8_t*)spice_realloc(buffer->buffer, buffer->capacity);
     247             :     }
     248           0 : }
     249             : 
     250           0 : int spice_buffer_empty(SpiceBuffer *buffer)
     251             : {
     252           0 :     return buffer->offset == 0;
     253             : }
     254             : 
     255           0 : uint8_t *spice_buffer_end(SpiceBuffer *buffer)
     256             : {
     257           0 :     return buffer->buffer + buffer->offset;
     258             : }
     259             : 
     260           0 : void spice_buffer_reset(SpiceBuffer *buffer)
     261             : {
     262           0 :     buffer->offset = 0;
     263           0 : }
     264             : 
     265           0 : void spice_buffer_free(SpiceBuffer *buffer)
     266             : {
     267           0 :     free(buffer->buffer);
     268           0 :     buffer->offset = 0;
     269           0 :     buffer->capacity = 0;
     270           0 :     buffer->buffer = NULL;
     271           0 : }
     272             : 
     273           0 : void spice_buffer_append(SpiceBuffer *buffer, const void *data, size_t len)
     274             : {
     275           0 :     spice_buffer_reserve(buffer, len);
     276           0 :     memcpy(buffer->buffer + buffer->offset, data, len);
     277           0 :     buffer->offset += len;
     278           0 : }
     279             : 
     280           0 : size_t spice_buffer_copy(SpiceBuffer *buffer, void *dest, size_t len)
     281             : {
     282           0 :     len = MIN(buffer->offset, len);
     283           0 :     memcpy(dest, buffer->buffer, len);
     284           0 :     return len;
     285             : }
     286             : 
     287           0 : size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len)
     288             : {
     289           0 :     len = MIN(buffer->offset, len);
     290           0 :     memmove(buffer->buffer, buffer->buffer + len, buffer->offset - len);
     291           0 :     buffer->offset -= len;
     292           0 :     return len;
     293             : }
     294             : 
     295             : #ifdef SPICE_DEBUG_ALIGNMENT
     296             : void spice_alignment_warning(const char *loc, void *p, unsigned sz)
     297             : {
     298             :     static const char *last_loc = NULL;
     299             :     if (loc != last_loc) {
     300             :         last_loc = loc;
     301             :         spice_log(G_LOG_LEVEL_WARNING, loc, __FUNCTION__,
     302             :                   "Misaligned access at %p, alignment %u", p, sz);
     303             :     }
     304             : }
     305             : 
     306             : void spice_alignment_debug(const char *loc, void *p, unsigned sz)
     307             : {
     308             :     static const char *last_loc = NULL;
     309             :     if (loc != last_loc) {
     310             :         last_loc = loc;
     311             :         spice_log(G_LOG_LEVEL_DEBUG, loc, __FUNCTION__,
     312             :                   "Expected misaligned access at %p, alignment %u", p, sz);
     313             :     }
     314             : }
     315             : #endif // SPICE_DEBUG_ALIGNMENT

Generated by: LCOV version 1.14