/src/suricata7/src/util-buffer.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2023 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \file |
20 | | * |
21 | | * \author Anoop Saldanha <anoopsaldanha@gmail.com> |
22 | | */ |
23 | | |
24 | | #include "suricata-common.h" |
25 | | #include "suricata.h" |
26 | | #include "util-debug.h" |
27 | | #include "util-buffer.h" |
28 | | |
29 | | /* 10 mb */ |
30 | 197 | #define MAX_LIMIT 10485760 |
31 | | |
32 | | MemBuffer *MemBufferCreateNew(uint32_t size) |
33 | 130 | { |
34 | 130 | sc_errno = SC_OK; |
35 | 130 | if (size > MAX_LIMIT) { |
36 | 0 | SCLogWarning("Mem buffer asked to create " |
37 | 0 | "buffer with size greater than API limit - %d", |
38 | 0 | MAX_LIMIT); |
39 | 0 | sc_errno = SC_EINVAL; |
40 | 0 | return NULL; |
41 | 0 | } |
42 | | |
43 | 130 | size_t total_size = size + sizeof(MemBuffer); |
44 | | |
45 | 130 | MemBuffer *buffer = SCCalloc(1, total_size); |
46 | 130 | if (unlikely(buffer == NULL)) { |
47 | 0 | sc_errno = SC_ENOMEM; |
48 | 0 | return NULL; |
49 | 0 | } |
50 | 130 | buffer->size = size; |
51 | 130 | return buffer; |
52 | 130 | } |
53 | | |
54 | | /** \brief expand membuffer by size of 'expand_by' |
55 | | * |
56 | | * If expansion failed, buffer will still be valid. |
57 | | * |
58 | | * \retval result 0 ok, -1 expansion failed |
59 | | */ |
60 | 67 | int MemBufferExpand(MemBuffer **buffer, uint32_t expand_by) { |
61 | 67 | if (((*buffer)->size + expand_by) > MAX_LIMIT) { |
62 | 0 | SCLogWarning("Mem buffer asked to create " |
63 | 0 | "buffer with size greater than API limit - %d", |
64 | 0 | MAX_LIMIT); |
65 | 0 | return -1; |
66 | 0 | } |
67 | | |
68 | | /* Adjust expand_by to next multiple of 4k. */ |
69 | 67 | if (expand_by % 4096 != 0) { |
70 | 66 | expand_by = expand_by - (expand_by % 4096) + 4096; |
71 | 66 | } |
72 | | |
73 | 67 | size_t total_size = (*buffer)->size + sizeof(MemBuffer) + expand_by; |
74 | | |
75 | 67 | MemBuffer *tbuffer = SCRealloc(*buffer, total_size); |
76 | 67 | if (unlikely(tbuffer == NULL)) { |
77 | 0 | return -1; |
78 | 0 | } |
79 | 67 | *buffer = tbuffer; |
80 | 67 | (*buffer)->size += expand_by; |
81 | | |
82 | 67 | SCLogDebug("expanded buffer by %u, size is now %u", expand_by, (*buffer)->size); |
83 | 67 | return 0; |
84 | 67 | } |
85 | | |
86 | | void MemBufferFree(MemBuffer *buffer) |
87 | 0 | { |
88 | 0 | SCFree(buffer); |
89 | |
|
90 | 0 | return; |
91 | 0 | } |
92 | | |
93 | | void MemBufferPrintToFP(MemBuffer *buffer, FILE *fp) |
94 | 0 | { |
95 | 0 | for (uint32_t i = 0; i < buffer->offset; i++) { |
96 | 0 | if (isprint(buffer->buffer[i])) |
97 | 0 | fprintf(fp, "%c", buffer->buffer[i]); |
98 | 0 | else |
99 | 0 | fprintf(fp, "|%02X|", buffer->buffer[i]); |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | size_t MemBufferPrintToFPAsString(MemBuffer *b, FILE *fp) |
104 | 0 | { |
105 | 0 | return fwrite(MEMBUFFER_BUFFER(b), sizeof(uint8_t), MEMBUFFER_OFFSET(b), fp); |
106 | 0 | } |
107 | | |
108 | | void MemBufferPrintToFPAsHex(MemBuffer *b, FILE *fp) |
109 | 0 | { |
110 | 0 | for (uint32_t i = 0; i < MEMBUFFER_OFFSET(b); i++) { |
111 | 0 | if (MEMBUFFER_OFFSET(b) % 8 == 0) |
112 | 0 | fprintf(fp, "\n"); |
113 | 0 | fprintf(fp, " %02X", b->buffer[i]); |
114 | 0 | } |
115 | 0 | } |
116 | | |
117 | | uint32_t MemBufferWriteRaw(MemBuffer *dst, const uint8_t *raw, const uint32_t raw_len) |
118 | 12.8M | { |
119 | 12.8M | uint32_t write_len; |
120 | 12.8M | if (raw_len >= dst->size - dst->offset) { |
121 | 115k | SCLogDebug("Truncating data write since it exceeded buffer limit of %" PRIu32, dst->size); |
122 | 115k | write_len = dst->size - dst->offset - 1; |
123 | 12.7M | } else { |
124 | 12.7M | write_len = raw_len; |
125 | 12.7M | } |
126 | 12.8M | memcpy(dst->buffer + dst->offset, raw, write_len); |
127 | 12.8M | dst->offset += write_len; |
128 | 12.8M | dst->buffer[dst->offset] = '\0'; |
129 | 12.8M | return write_len; |
130 | 12.8M | } |
131 | | |
132 | | void MemBufferWriteString(MemBuffer *dst, const char *fmt, ...) |
133 | 15.1M | { |
134 | 15.1M | uint32_t available = dst->size - dst->offset; |
135 | 15.1M | uint32_t max_string_size = MIN(available, 2048); |
136 | 15.1M | va_list ap; |
137 | 15.1M | char string[max_string_size]; |
138 | 15.1M | va_start(ap, fmt); |
139 | 15.1M | int written = vsnprintf(string, sizeof(string), fmt, ap); |
140 | 15.1M | va_end(ap); |
141 | 15.1M | if (written < 0) { |
142 | 0 | return; |
143 | 15.1M | } else if ((uint32_t)written > max_string_size) { |
144 | 509 | SCLogDebug("Truncating data write since it exceeded buffer " |
145 | 509 | "limit of %" PRIu32, |
146 | 509 | dst->size); |
147 | 509 | } |
148 | 15.1M | size_t string_size = strlen(string); |
149 | 15.1M | memcpy(dst->buffer + dst->offset, string, string_size); |
150 | 15.1M | dst->offset += string_size; |
151 | 15.1M | dst->buffer[dst->offset] = '\0'; |
152 | 15.1M | } |