Coverage Report

Created: 2023-03-26 07:37

/src/yara/libyara/notebook.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2020. The YARA Authors. All Rights Reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
1. Redistributions of source code must retain the above copyright notice, this
8
list of conditions and the following disclaimer.
9
10
2. Redistributions in binary form must reproduce the above copyright notice,
11
this list of conditions and the following disclaimer in the documentation and/or
12
other materials provided with the distribution.
13
14
3. Neither the name of the copyright holder nor the names of its contributors
15
may be used to endorse or promote products derived from this software without
16
specific prior written permission.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <assert.h>
31
#include <stdint.h>
32
#include <yara/error.h>
33
#include <yara/mem.h>
34
#include <yara/notebook.h>
35
36
// Forward declaration of YR_NOTEBOOK_PAGE.
37
typedef struct YR_NOTEBOOK_PAGE YR_NOTEBOOK_PAGE;
38
39
// A notebook is a data structure that can be used for allocating memory
40
// space in the same way malloc() would do. However, the buffers returned
41
// by yr_notebook_alloc() are backed by a larger buffer reserved by the notebook
42
// beforehand called a "page". The notebook fulfills the allocations performed
43
// via yr_notebook_alloc() with space taken from the current page, or creates
44
// a new page when necessary. It's recommended that the page size is at least
45
// 4x the size of the buffers you plan to allocate with yr_notebook_alloc().
46
//
47
// Once the notebook is destroyed all the pages are freed, and consequently
48
// all the buffers allocated via yr_notebook_alloc().
49
struct YR_NOTEBOOK
50
{
51
  // Size of each page in the notebook.
52
  size_t page_size;
53
  // Pointer to the first page in the book, this is also the most recently
54
  // created page, the one that is being filled.
55
  YR_NOTEBOOK_PAGE* page_list_head;
56
};
57
58
struct YR_NOTEBOOK_PAGE
59
{
60
  // Amount of bytes in the page that are actually used.
61
  size_t used;
62
  // Pointer to next page.
63
  YR_NOTEBOOK_PAGE* next;
64
  // Page's data.
65
  uint8_t data[0];
66
};
67
68
////////////////////////////////////////////////////////////////////////////////
69
// Creates a new notebook. The notebook initially has a single page of the
70
// specified size, but more pages are created if needed.
71
//
72
// Args:
73
//   page_size: Size of each page in the notebook.
74
//   notebook: Address of a pointer to the newly created notebook.
75
//
76
// Returns:
77
//   ERROR_SUCCESS
78
//   ERROR_INSUFFICIENT_MEMORY
79
//
80
int yr_notebook_create(size_t page_size, YR_NOTEBOOK** notebook)
81
6.13k
{
82
6.13k
  YR_NOTEBOOK* new_notebook = yr_malloc(sizeof(YR_NOTEBOOK));
83
84
6.13k
  if (new_notebook == NULL)
85
0
    return ERROR_INSUFFICIENT_MEMORY;
86
87
6.13k
  new_notebook->page_list_head = yr_malloc(
88
6.13k
      sizeof(YR_NOTEBOOK_PAGE) + page_size);
89
90
6.13k
  if (new_notebook->page_list_head == NULL)
91
0
  {
92
0
    yr_free(new_notebook);
93
0
    return ERROR_INSUFFICIENT_MEMORY;
94
0
  }
95
96
6.13k
  new_notebook->page_size = page_size;
97
6.13k
  new_notebook->page_list_head->used = 0;
98
6.13k
  new_notebook->page_list_head->next = NULL;
99
100
6.13k
  *notebook = new_notebook;
101
102
6.13k
  return ERROR_SUCCESS;
103
6.13k
}
104
105
////////////////////////////////////////////////////////////////////////////////
106
// Destroys a notebook and frees all the notebook's pages.
107
//
108
// Args:
109
//   notebook: Pointer to the notebook being destroyed.
110
//
111
// Returns:
112
//   ERROR_SUCCESS
113
//
114
int yr_notebook_destroy(YR_NOTEBOOK* notebook)
115
6.13k
{
116
6.13k
  YR_NOTEBOOK_PAGE* page = notebook->page_list_head;
117
118
12.2k
  while (page != NULL)
119
6.13k
  {
120
6.13k
    YR_NOTEBOOK_PAGE* next = page->next;
121
6.13k
    yr_free(page);
122
6.13k
    page = next;
123
6.13k
  }
124
125
6.13k
  yr_free(notebook);
126
127
6.13k
  return ERROR_SUCCESS;
128
6.13k
}
129
130
////////////////////////////////////////////////////////////////////////////////
131
// Allocates a memory buffer from a notebook. The memory is freed when the
132
// notebook is destroyed, allocated buffers can't be freed individually. The
133
// returned buffer is guaranteed to be aligned to an 8-byte boundary.
134
//
135
// Args:
136
//   notebook: Pointer to the notebook.
137
//   size: Size of the allocated memory.
138
//
139
// Returns:
140
//   Pointer to the allocated memory, or NULL if the allocation fails.
141
//
142
void* yr_notebook_alloc(YR_NOTEBOOK* notebook, size_t size)
143
0
{
144
  // Round up the size to a multiple of 8, which also implies that the returned
145
  // pointers are aligned to 8 bytes. The 8-byte alignment is required by some
146
  // platforms (e.g. ARM and Sparc) that have strict alignment requirements when
147
  // deferrencing pointers to types larger than a byte.
148
0
  size = (size + 7) & ~0x7;
149
150
  // The requested memory size can't be larger than a notebook's page.
151
0
  assert(size <= notebook->page_size);
152
153
  // If the requested size doesn't fit in current page's free space, allocate
154
  // a new page.
155
0
  if (notebook->page_size - notebook->page_list_head->used < size)
156
0
  {
157
0
    YR_NOTEBOOK_PAGE* new_page = yr_malloc(
158
0
        sizeof(YR_NOTEBOOK_PAGE) + notebook->page_size);
159
160
0
    if (new_page == NULL)
161
0
      return NULL;
162
163
0
    new_page->used = 0;
164
0
    new_page->next = notebook->page_list_head;
165
0
    notebook->page_list_head = new_page;
166
0
  }
167
168
0
  void* ptr = notebook->page_list_head->data + notebook->page_list_head->used;
169
170
0
  notebook->page_list_head->used += size;
171
172
0
  return ptr;
173
0
}