line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/** |
2
|
|
|
|
|
|
|
* @file psbuf.c |
3
|
|
|
|
|
|
|
* @version 950bba4 (HEAD -> master) |
4
|
|
|
|
|
|
|
* |
5
|
|
|
|
|
|
|
* Implementation of API for handling buffers containing binary data. |
6
|
|
|
|
|
|
|
*/ |
7
|
|
|
|
|
|
|
/* |
8
|
|
|
|
|
|
|
* Copyright (c) 2017 INSIDE Secure Corporation |
9
|
|
|
|
|
|
|
* All Rights Reserved |
10
|
|
|
|
|
|
|
* |
11
|
|
|
|
|
|
|
* The latest version of this code is available at http://www.matrixssl.org |
12
|
|
|
|
|
|
|
* |
13
|
|
|
|
|
|
|
* This software is open source; you can redistribute it and/or modify |
14
|
|
|
|
|
|
|
* it under the terms of the GNU General Public License as published by |
15
|
|
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
16
|
|
|
|
|
|
|
* (at your option) any later version. |
17
|
|
|
|
|
|
|
* |
18
|
|
|
|
|
|
|
* This General Public License does NOT permit incorporating this software |
19
|
|
|
|
|
|
|
* into proprietary programs. If you are unable to comply with the GPL, a |
20
|
|
|
|
|
|
|
* commercial license for this software may be purchased from INSIDE at |
21
|
|
|
|
|
|
|
* http://www.insidesecure.com/ |
22
|
|
|
|
|
|
|
* |
23
|
|
|
|
|
|
|
* This program is distributed in WITHOUT ANY WARRANTY; without even the |
24
|
|
|
|
|
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
25
|
|
|
|
|
|
|
* See the GNU General Public License for more details. |
26
|
|
|
|
|
|
|
* |
27
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License |
28
|
|
|
|
|
|
|
* along with this program; if not, write to the Free Software |
29
|
|
|
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
30
|
|
|
|
|
|
|
* http://www.gnu.org/copyleft/gpl.html |
31
|
|
|
|
|
|
|
*/ |
32
|
|
|
|
|
|
|
/******************************************************************************/ |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
#include |
35
|
|
|
|
|
|
|
#include |
36
|
|
|
|
|
|
|
#include |
37
|
|
|
|
|
|
|
#include |
38
|
|
|
|
|
|
|
#include |
39
|
|
|
|
|
|
|
#include "coreApi.h" |
40
|
|
|
|
|
|
|
#include "osdep.h" |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
/* Omit debug printouts. */ |
43
|
|
|
|
|
|
|
#define debugf(...) do { } while (0) |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
/* This address is indicator for static allocations pool, and does not |
46
|
|
|
|
|
|
|
need to point to any valid pool. The pool cannot be NULL, because |
47
|
|
|
|
|
|
|
NULL is reserved for "default memory pool". */ |
48
|
|
|
|
|
|
|
psPool_t * const psStaticAllocationsPool = |
49
|
|
|
|
|
|
|
(psPool_t *) &psStaticAllocationsPool; |
50
|
|
|
|
|
|
|
|
51
|
0
|
|
|
|
|
|
void *psBufInit(psPool_t *pool, psBuf_t *buf, size_t capacity) |
52
|
|
|
|
|
|
|
{ |
53
|
0
|
|
|
|
|
|
buf->buf = psMalloc(pool, capacity); |
54
|
0
|
|
|
|
|
|
buf->start = buf->buf; |
55
|
0
|
|
|
|
|
|
buf->end = buf->start; |
56
|
0
|
0
|
|
|
|
|
buf->size = buf->buf ? capacity : 0; |
57
|
0
|
|
|
|
|
|
return buf->buf; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
0
|
|
|
|
|
|
void psBufUninit(psPool_t *pool, psBuf_t *buf) |
61
|
|
|
|
|
|
|
{ |
62
|
0
|
0
|
|
|
|
|
if (pool != psStaticAllocationsPool) |
63
|
|
|
|
|
|
|
{ |
64
|
0
|
|
|
|
|
|
psFree(buf->buf, pool); |
65
|
|
|
|
|
|
|
} |
66
|
0
|
|
|
|
|
|
buf->buf = NULL; |
67
|
0
|
|
|
|
|
|
buf->start = NULL; |
68
|
0
|
|
|
|
|
|
buf->end = NULL; |
69
|
0
|
|
|
|
|
|
buf->size = 0; |
70
|
0
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
void *psBufDetach(psPool_t *pool, psBuf_t *buf, size_t *len_p) |
73
|
|
|
|
|
|
|
{ |
74
|
|
|
|
|
|
|
void *new; |
75
|
0
|
|
|
|
|
|
size_t len = buf->end - buf->start; |
76
|
|
|
|
|
|
|
|
77
|
0
|
0
|
|
|
|
|
new = psMalloc(pool, len ? len : 1); |
78
|
0
|
0
|
|
|
|
|
if (new) |
79
|
|
|
|
|
|
|
{ |
80
|
0
|
|
|
|
|
|
memcpy(new, buf->start, len); |
81
|
0
|
|
|
|
|
|
*len_p = len; |
82
|
|
|
|
|
|
|
} |
83
|
0
|
|
|
|
|
|
psBufUninit(pool, buf); |
84
|
0
|
|
|
|
|
|
return new; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
|
int32_t psBufFromData(psPool_t *pool, psBuf_t *buf, const void *data, size_t len) |
88
|
|
|
|
|
|
|
{ |
89
|
0
|
|
|
|
|
|
void *new = NULL; |
90
|
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
|
buf->buf = buf->start = buf->end = NULL; |
92
|
0
|
|
|
|
|
|
buf->size = 0; |
93
|
|
|
|
|
|
|
|
94
|
0
|
0
|
|
|
|
|
if (data != NULL) |
95
|
|
|
|
|
|
|
{ |
96
|
0
|
0
|
|
|
|
|
new = psMalloc(pool, len ? len : 1); |
97
|
0
|
0
|
|
|
|
|
if (new != NULL) |
98
|
|
|
|
|
|
|
{ |
99
|
0
|
|
|
|
|
|
buf->buf = buf->start = buf->end = new; |
100
|
0
|
|
|
|
|
|
buf->size = len; |
101
|
0
|
|
|
|
|
|
buf->end += len; |
102
|
0
|
|
|
|
|
|
memcpy(new, data, len); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
} |
105
|
0
|
0
|
|
|
|
|
return new ? PS_SUCCESS : PS_MEM_FAIL; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
0
|
|
|
|
|
|
int32_t psBufFromStaticData(psBuf_t *buf, const void *data, size_t len) |
109
|
|
|
|
|
|
|
{ |
110
|
0
|
0
|
|
|
|
|
if (!data) |
111
|
|
|
|
|
|
|
{ |
112
|
0
|
|
|
|
|
|
len = 0; |
113
|
|
|
|
|
|
|
} |
114
|
0
|
|
|
|
|
|
buf->buf = buf->start = buf->end = (void *) data; |
115
|
0
|
|
|
|
|
|
buf->size = len; |
116
|
0
|
|
|
|
|
|
buf->end += len; |
117
|
0
|
0
|
|
|
|
|
return data ? PS_SUCCESS : PS_ARG_FAIL; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
0
|
|
|
|
|
|
int32_t psBufEmptyFromPointerSize(psBuf_t *buf, void *data, size_t len) |
121
|
|
|
|
|
|
|
{ |
122
|
0
|
0
|
|
|
|
|
if (!data) |
123
|
|
|
|
|
|
|
{ |
124
|
0
|
|
|
|
|
|
len = 0; |
125
|
|
|
|
|
|
|
} |
126
|
0
|
|
|
|
|
|
buf->buf = buf->start = buf->end = (void *) data; |
127
|
0
|
|
|
|
|
|
buf->size = len; |
128
|
0
|
0
|
|
|
|
|
return data ? PS_SUCCESS : PS_ARG_FAIL; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
0
|
|
|
|
|
|
char *psBufAsHex(psPool_t *pool, const psBuf_t *buf) |
132
|
|
|
|
|
|
|
{ |
133
|
|
|
|
|
|
|
char *hexstr; |
134
|
0
|
|
|
|
|
|
size_t len = buf->end - buf->start; |
135
|
|
|
|
|
|
|
|
136
|
0
|
|
|
|
|
|
hexstr = psMalloc(pool, len * 2 + 1); |
137
|
0
|
0
|
|
|
|
|
if (hexstr) |
138
|
|
|
|
|
|
|
{ |
139
|
|
|
|
|
|
|
size_t i; |
140
|
0
|
|
|
|
|
|
hexstr[0] = 0; |
141
|
0
|
0
|
|
|
|
|
for (i = 0; i < len; i++) |
142
|
|
|
|
|
|
|
{ |
143
|
0
|
|
|
|
|
|
sprintf(hexstr + i * 2, "%02x", buf->start[i]); |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
} |
146
|
0
|
|
|
|
|
|
return hexstr; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
0
|
|
|
|
|
|
size_t psBufGetMaxAppendSize(const psBuf_t *buf) |
150
|
|
|
|
|
|
|
{ |
151
|
0
|
|
|
|
|
|
const unsigned char *loc = buf->end; |
152
|
0
|
|
|
|
|
|
const unsigned char *bufend = buf->buf + buf->size; |
153
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
return bufend - loc; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
|
void *psBufAppendSize(psBuf_t *buf, size_t sz) |
158
|
|
|
|
|
|
|
{ |
159
|
0
|
|
|
|
|
|
unsigned char *loc = buf->end; |
160
|
0
|
|
|
|
|
|
unsigned char *bufend = buf->buf + buf->size; |
161
|
|
|
|
|
|
|
|
162
|
0
|
0
|
|
|
|
|
if (loc + sz <= bufend) |
163
|
|
|
|
|
|
|
{ |
164
|
0
|
|
|
|
|
|
buf->end += sz; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
else |
167
|
|
|
|
|
|
|
{ |
168
|
0
|
|
|
|
|
|
loc = NULL; |
169
|
|
|
|
|
|
|
} |
170
|
0
|
|
|
|
|
|
return loc; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
|
void psBufReservePrepend(psBuf_t *buf, size_t sz) |
174
|
|
|
|
|
|
|
{ |
175
|
0
|
|
|
|
|
|
unsigned char *bufend = buf->buf + buf->size; |
176
|
0
|
|
|
|
|
|
unsigned char *loc = buf->end; |
177
|
|
|
|
|
|
|
|
178
|
0
|
0
|
|
|
|
|
assert(buf->start == buf->end); /* Must be done at the beginning. */ |
179
|
|
|
|
|
|
|
|
180
|
0
|
0
|
|
|
|
|
if (loc + sz <= bufend) |
181
|
|
|
|
|
|
|
{ |
182
|
0
|
|
|
|
|
|
buf->start += sz; |
183
|
0
|
|
|
|
|
|
buf->end += sz; |
184
|
|
|
|
|
|
|
} |
185
|
0
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
0
|
|
|
|
|
|
size_t psBufGetMaxPrependSize(const psBuf_t *buf) |
188
|
|
|
|
|
|
|
{ |
189
|
0
|
|
|
|
|
|
return buf->start - buf->buf; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
0
|
|
|
|
|
|
void *psBufGetData(psBuf_t *buf) |
193
|
|
|
|
|
|
|
{ |
194
|
0
|
|
|
|
|
|
return buf->start; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
0
|
|
|
|
|
|
size_t psBufGetDataSize(const psBuf_t *buf) |
198
|
|
|
|
|
|
|
{ |
199
|
0
|
|
|
|
|
|
return buf->end - buf->start; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
void *psBufPrependSize(psBuf_t *buf, size_t sz) |
203
|
|
|
|
|
|
|
{ |
204
|
0
|
0
|
|
|
|
|
if (buf->buf <= buf->start && buf->buf + sz <= buf->start) |
|
|
0
|
|
|
|
|
|
205
|
|
|
|
|
|
|
{ |
206
|
0
|
|
|
|
|
|
buf->start -= sz; |
207
|
0
|
|
|
|
|
|
return buf->start; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
0
|
|
|
|
|
|
return NULL; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
0
|
|
|
|
|
|
void psBufNormalize(psBuf_t *buf) |
214
|
|
|
|
|
|
|
{ |
215
|
0
|
|
|
|
|
|
size_t sz = psBufGetMaxPrependSize(buf); |
216
|
|
|
|
|
|
|
|
217
|
0
|
0
|
|
|
|
|
if (sz > 0) |
218
|
|
|
|
|
|
|
{ |
219
|
|
|
|
|
|
|
/* There is some prepend size. Delete it via memmove() that |
220
|
|
|
|
|
|
|
moves data to the beginning of the buffer. */ |
221
|
0
|
|
|
|
|
|
memmove(buf->buf, buf->start, buf->end - buf->start); |
222
|
0
|
|
|
|
|
|
buf->start = buf->buf; |
223
|
0
|
|
|
|
|
|
buf->end -= sz; |
224
|
|
|
|
|
|
|
} |
225
|
0
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
0
|
|
|
|
|
|
int32_t psBufCopyDataN(psBuf_t *buf, size_t reqLen, |
228
|
|
|
|
|
|
|
unsigned char *target, size_t *targetlen) |
229
|
|
|
|
|
|
|
{ |
230
|
|
|
|
|
|
|
size_t len; |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
/* Compute actual processing size (the smaller of [data avail, reqLen]) */ |
233
|
0
|
|
|
|
|
|
len = psBufGetDataSize(buf); |
234
|
0
|
0
|
|
|
|
|
if (reqLen < len) |
235
|
|
|
|
|
|
|
{ |
236
|
0
|
|
|
|
|
|
len = reqLen; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
/* Check there will be no overflow. */ |
240
|
0
|
0
|
|
|
|
|
if (len > *targetlen) |
241
|
|
|
|
|
|
|
{ |
242
|
0
|
|
|
|
|
|
*targetlen = len; |
243
|
0
|
|
|
|
|
|
return PS_OUTPUT_LENGTH; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
/* Process copy operation + move buffer pointer. */ |
247
|
0
|
|
|
|
|
|
memcpy(target, psBufGetData(buf), len); |
248
|
0
|
|
|
|
|
|
buf->start += len; |
249
|
0
|
|
|
|
|
|
*targetlen = len; |
250
|
0
|
|
|
|
|
|
return PS_SUCCESS; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
0
|
|
|
|
|
|
void *psDynBufInit(psPool_t *pool, psDynBuf_t *db, size_t capacity) |
254
|
|
|
|
|
|
|
{ |
255
|
0
|
|
|
|
|
|
void *mem = psBufInit(pool, &db->buf, capacity); |
256
|
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
db->pool = pool; |
258
|
0
|
|
|
|
|
|
db->err = (mem == NULL); |
259
|
0
|
|
|
|
|
|
db->master = NULL; |
260
|
0
|
|
|
|
|
|
return mem; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
0
|
|
|
|
|
|
void psDynBufUninit(psDynBuf_t *db) |
264
|
|
|
|
|
|
|
{ |
265
|
0
|
|
|
|
|
|
psBufUninit(db->pool, &db->buf); |
266
|
0
|
|
|
|
|
|
db->err = 0; |
267
|
0
|
|
|
|
|
|
db->pool = NULL; |
268
|
0
|
|
|
|
|
|
db->master = NULL; |
269
|
0
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
void *psDynBufDetach(psDynBuf_t *db, size_t *len_p) |
272
|
|
|
|
|
|
|
{ |
273
|
|
|
|
|
|
|
void *new; |
274
|
|
|
|
|
|
|
|
275
|
0
|
0
|
|
|
|
|
if (db->err) |
276
|
|
|
|
|
|
|
{ |
277
|
0
|
|
|
|
|
|
psDynBufUninit(db); |
278
|
0
|
|
|
|
|
|
return NULL; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
0
|
|
|
|
|
|
new = psBufDetach(db->pool, &db->buf, len_p); |
282
|
0
|
|
|
|
|
|
db->pool = NULL; |
283
|
0
|
|
|
|
|
|
return new; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
static |
287
|
0
|
|
|
|
|
|
void assert_subbuf(psDynBuf_t *sub) |
288
|
|
|
|
|
|
|
{ |
289
|
|
|
|
|
|
|
const psDynBuf_t *db; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
/* Has master. */ |
292
|
0
|
0
|
|
|
|
|
assert(sub->master != NULL); |
293
|
|
|
|
|
|
|
|
294
|
0
|
|
|
|
|
|
db = sub->master; |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
/* Does not have pool */ |
297
|
0
|
0
|
|
|
|
|
assert(sub->pool == NULL); |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
/* The buf begin and is within master allocated data area. */ |
300
|
0
|
0
|
|
|
|
|
assert(sub->buf.buf >= db->buf.start && sub->buf.buf <= db->buf.end); |
|
|
0
|
|
|
|
|
|
301
|
0
|
0
|
|
|
|
|
assert(sub->buf.buf + sub->buf.size >= db->buf.start && |
|
|
0
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub->buf.buf + sub->buf.size <= db->buf.end); |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
#ifdef PSBUF_DEBUG_WITH_MEMSET |
305
|
|
|
|
|
|
|
/* For debugging: Mark head and tail visually. */ |
306
|
|
|
|
|
|
|
memset(sub->buf.buf, '(', sub->buf.start - sub->buf.buf); |
307
|
|
|
|
|
|
|
memset(sub->buf.end, ')', sub->buf.buf + sub->buf.size - sub->buf.end); |
308
|
|
|
|
|
|
|
#endif /* PSBUF_DEBUG_WITH_MEMSET */ |
309
|
0
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
|
static void *psDynBufGrow(psDynBuf_t *db, size_t head_sz, size_t tail_sz) |
312
|
|
|
|
|
|
|
{ |
313
|
|
|
|
|
|
|
void *alloc; |
314
|
|
|
|
|
|
|
void *loc; |
315
|
|
|
|
|
|
|
psBuf_t new; |
316
|
0
|
|
|
|
|
|
size_t headroom = db->buf.start - db->buf.buf; |
317
|
0
|
|
|
|
|
|
size_t tailroom = (db->buf.buf + db->buf.size) - db->buf.end; |
318
|
0
|
|
|
|
|
|
size_t filled = db->buf.end - db->buf.start; |
319
|
|
|
|
|
|
|
size_t offset; |
320
|
|
|
|
|
|
|
size_t offset_tail; |
321
|
|
|
|
|
|
|
|
322
|
0
|
0
|
|
|
|
|
if (db->err) |
323
|
|
|
|
|
|
|
{ |
324
|
0
|
|
|
|
|
|
return NULL; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
0
|
0
|
|
|
|
|
if (head_sz != 0 && head_sz < PS_DYNBUF_GROW) |
|
|
0
|
|
|
|
|
|
328
|
|
|
|
|
|
|
{ |
329
|
0
|
|
|
|
|
|
head_sz = PS_DYNBUF_GROW; |
330
|
|
|
|
|
|
|
} |
331
|
0
|
0
|
|
|
|
|
if (tail_sz < PS_DYNBUF_GROW) |
332
|
|
|
|
|
|
|
{ |
333
|
0
|
|
|
|
|
|
tail_sz = PS_DYNBUF_GROW; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
0
|
0
|
|
|
|
|
if (db->master) |
337
|
|
|
|
|
|
|
{ |
338
|
0
|
|
|
|
|
|
offset = db->buf.buf - db->master->buf.start; |
339
|
0
|
|
|
|
|
|
offset_tail = db->master->buf.end - (db->buf.buf + db->buf.size); |
340
|
|
|
|
|
|
|
debugf("Sub Grow: %zu+%zu+%zu => %zu+%zu+%zu; sub @ pos=%zd...-%zd\n", |
341
|
|
|
|
|
|
|
headroom, filled, tailroom, headroom + head_sz, filled, tailroom + tail_sz, offset, offset_tail); |
342
|
0
|
|
|
|
|
|
assert_subbuf(db); |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
#ifdef PSBUF_DEBUG_WITH_MEMSET |
345
|
|
|
|
|
|
|
/* For debugging: */ |
346
|
|
|
|
|
|
|
memset(db->buf.buf, '{', headroom); |
347
|
|
|
|
|
|
|
memset(db->buf.end, '}', tailroom); |
348
|
|
|
|
|
|
|
#endif /* PSBUF_DEBUG_WITH_MEMSET */ |
349
|
|
|
|
|
|
|
|
350
|
0
|
|
|
|
|
|
loc = psDynBufGrow(db->master, 0, head_sz + tail_sz); |
351
|
0
|
0
|
|
|
|
|
if (loc) |
352
|
|
|
|
|
|
|
{ |
353
|
0
|
|
|
|
|
|
db->master->buf.end += head_sz + tail_sz; |
354
|
0
|
0
|
|
|
|
|
if (offset_tail) |
355
|
|
|
|
|
|
|
{ |
356
|
0
|
|
|
|
|
|
memmove(db->master->buf.end - offset_tail, |
357
|
0
|
|
|
|
|
|
db->master->buf.end - offset_tail - head_sz - tail_sz, |
358
|
|
|
|
|
|
|
offset_tail); |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
|
db->buf.buf = db->master->buf.start + offset; |
362
|
0
|
|
|
|
|
|
db->buf.start = db->buf.buf + headroom + head_sz; |
363
|
0
|
0
|
|
|
|
|
if (head_sz > 0) |
364
|
|
|
|
|
|
|
{ |
365
|
0
|
|
|
|
|
|
memmove(db->buf.start, |
366
|
0
|
|
|
|
|
|
db->buf.start - head_sz, |
367
|
|
|
|
|
|
|
filled); |
368
|
|
|
|
|
|
|
} |
369
|
0
|
|
|
|
|
|
db->buf.end = db->buf.start + filled; |
370
|
0
|
|
|
|
|
|
db->buf.size = head_sz + headroom + filled + |
371
|
|
|
|
|
|
|
tailroom + tail_sz; |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
debugf("Sub Grown: sub @ pos=%d, %zd bytes (%zd+%zd+%zd)\n", |
374
|
|
|
|
|
|
|
(int) (db->buf.buf - db->master->buf.start), |
375
|
|
|
|
|
|
|
db->buf.size, db->buf.start - db->buf.buf, |
376
|
|
|
|
|
|
|
db->buf.end - db->buf.start, db->buf.buf + db->buf.size - db->buf.end); |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
#ifdef PSBUF_DEBUG_WITH_MEMSET |
379
|
|
|
|
|
|
|
/* For debugging: */ |
380
|
|
|
|
|
|
|
memset(db->buf.buf, '<', head_sz + headroom); |
381
|
|
|
|
|
|
|
memset(db->buf.end, '>', tail_sz + tailroom); |
382
|
|
|
|
|
|
|
#endif /* PSBUF_DEBUG_WITH_MEMSET */ |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
else |
385
|
|
|
|
|
|
|
{ |
386
|
0
|
|
|
|
|
|
db->err++; |
387
|
|
|
|
|
|
|
} |
388
|
0
|
|
|
|
|
|
assert_subbuf(db); |
389
|
|
|
|
|
|
|
|
390
|
0
|
|
|
|
|
|
return loc; |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
|
393
|
0
|
|
|
|
|
|
head_sz += headroom; |
394
|
0
|
|
|
|
|
|
tail_sz += tailroom; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
debugf("Grow: %zu+%zu+%zu => %zu+%zu+%zu\n", |
397
|
|
|
|
|
|
|
headroom, filled, tailroom, head_sz, filled, tail_sz); |
398
|
|
|
|
|
|
|
|
399
|
0
|
|
|
|
|
|
alloc = psBufInit(db->pool, &new, head_sz + filled + tail_sz); |
400
|
0
|
0
|
|
|
|
|
if (alloc) |
401
|
|
|
|
|
|
|
{ |
402
|
0
|
|
|
|
|
|
psBufReservePrepend(&new, head_sz); |
403
|
0
|
|
|
|
|
|
loc = psBufAppendSize(&new, filled); |
404
|
|
|
|
|
|
|
/* Just allocated so there is space. */ |
405
|
0
|
0
|
|
|
|
|
assert(loc != NULL); |
406
|
0
|
|
|
|
|
|
memcpy(loc, db->buf.start, filled); |
407
|
0
|
|
|
|
|
|
psBufUninit(db->pool, &db->buf); |
408
|
0
|
|
|
|
|
|
db->buf.buf = new.buf; |
409
|
0
|
|
|
|
|
|
db->buf.start = new.start; |
410
|
0
|
|
|
|
|
|
db->buf.end = new.end; |
411
|
0
|
|
|
|
|
|
db->buf.size = new.size; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
else |
414
|
|
|
|
|
|
|
{ |
415
|
0
|
|
|
|
|
|
db->err++; |
416
|
0
|
|
|
|
|
|
loc = NULL; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
0
|
|
|
|
|
|
return loc; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
|
void *psDynBufAppendSize(psDynBuf_t *db, size_t sz) |
423
|
|
|
|
|
|
|
{ |
424
|
0
|
|
|
|
|
|
unsigned char *loc = psBufAppendSize(&db->buf, sz); |
425
|
|
|
|
|
|
|
|
426
|
0
|
0
|
|
|
|
|
if (loc == NULL) |
427
|
|
|
|
|
|
|
{ |
428
|
0
|
0
|
|
|
|
|
if (psDynBufGrow(db, 0, sz)) |
429
|
|
|
|
|
|
|
{ |
430
|
0
|
|
|
|
|
|
loc = psBufAppendSize(&db->buf, sz); |
431
|
0
|
0
|
|
|
|
|
assert(loc != NULL); |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
} |
434
|
0
|
|
|
|
|
|
return loc; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
|
void *psDynBufAppendUtf8(psDynBuf_t *db, int chr) |
438
|
|
|
|
|
|
|
{ |
439
|
|
|
|
|
|
|
unsigned char *enc; |
440
|
0
|
|
|
|
|
|
unsigned int ch = (unsigned int) chr; |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
/* Do not encode characters outside valid UTF-8 range. */ |
443
|
0
|
0
|
|
|
|
|
if (ch > 0x1FFFF) |
444
|
|
|
|
|
|
|
{ |
445
|
0
|
|
|
|
|
|
db->err++; |
446
|
0
|
|
|
|
|
|
return NULL; |
447
|
|
|
|
|
|
|
} |
448
|
0
|
0
|
|
|
|
|
if (ch < 128) |
449
|
|
|
|
|
|
|
{ |
450
|
0
|
|
|
|
|
|
enc = psDynBufAppendSize(db, 1); |
451
|
0
|
0
|
|
|
|
|
if (enc) |
452
|
|
|
|
|
|
|
{ |
453
|
0
|
|
|
|
|
|
*enc = (unsigned char) ch; |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
} |
456
|
0
|
0
|
|
|
|
|
else if (ch <= 0x7FF) |
457
|
|
|
|
|
|
|
{ |
458
|
|
|
|
|
|
|
/* Two byte encoding. */ |
459
|
0
|
|
|
|
|
|
enc = psDynBufAppendSize(db, 2); |
460
|
0
|
0
|
|
|
|
|
if (enc) |
461
|
|
|
|
|
|
|
{ |
462
|
0
|
|
|
|
|
|
enc[0] = (unsigned char) (0xC0 | (ch >> 6)); |
463
|
0
|
|
|
|
|
|
enc[1] = (unsigned char) (0x80 | (ch & 63)); |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
} |
466
|
0
|
0
|
|
|
|
|
else if (ch <= 0xffff) |
467
|
|
|
|
|
|
|
{ |
468
|
|
|
|
|
|
|
/* Three byte encoding. */ |
469
|
0
|
|
|
|
|
|
enc = psDynBufAppendSize(db, 3); |
470
|
0
|
0
|
|
|
|
|
if (enc) |
471
|
|
|
|
|
|
|
{ |
472
|
0
|
|
|
|
|
|
enc[0] = (unsigned char) (0xE0 | (ch >> 12)); |
473
|
0
|
|
|
|
|
|
enc[1] = (unsigned char) (0x80 | ((ch >> 6) & 63)); |
474
|
0
|
|
|
|
|
|
enc[2] = (unsigned char) (0x80 | (ch & 63)); |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
else |
478
|
|
|
|
|
|
|
{ |
479
|
|
|
|
|
|
|
/* Four byte encoding. */ |
480
|
0
|
|
|
|
|
|
enc = psDynBufAppendSize(db, 4); |
481
|
0
|
0
|
|
|
|
|
if (enc) |
482
|
|
|
|
|
|
|
{ |
483
|
0
|
|
|
|
|
|
enc[0] = (unsigned char) (0xF0 | (ch >> 18)); |
484
|
0
|
|
|
|
|
|
enc[1] = (unsigned char) (0x80 | ((ch >> 12) & 63)); |
485
|
0
|
|
|
|
|
|
enc[2] = (unsigned char) (0x80 | ((ch >> 6) & 63)); |
486
|
0
|
|
|
|
|
|
enc[3] = (unsigned char) (0x80 | (ch & 63)); |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
} |
489
|
0
|
|
|
|
|
|
return enc; |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
|
493
|
0
|
|
|
|
|
|
void psDynBufReservePrepend(psDynBuf_t *db, size_t sz) |
494
|
|
|
|
|
|
|
{ |
495
|
|
|
|
|
|
|
/* This function only performs action if nothing has been pushed. |
496
|
|
|
|
|
|
|
The logic for prepending will make sure prepend succeeds even |
497
|
|
|
|
|
|
|
if there is no head room. */ |
498
|
0
|
0
|
|
|
|
|
if (db->buf.start == db->buf.end) |
499
|
|
|
|
|
|
|
{ |
500
|
0
|
|
|
|
|
|
psBufReservePrepend(&db->buf, sz); |
501
|
|
|
|
|
|
|
} |
502
|
0
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
0
|
|
|
|
|
|
void *psDynBufPrependSize(psDynBuf_t *db, size_t sz) |
505
|
|
|
|
|
|
|
{ |
506
|
0
|
|
|
|
|
|
unsigned char *loc = psBufPrependSize(&db->buf, sz); |
507
|
|
|
|
|
|
|
|
508
|
0
|
0
|
|
|
|
|
if (loc == NULL) |
509
|
|
|
|
|
|
|
{ |
510
|
0
|
0
|
|
|
|
|
if (psDynBufGrow(db, sz, 0)) |
511
|
|
|
|
|
|
|
{ |
512
|
0
|
|
|
|
|
|
loc = psBufPrependSize(&db->buf, sz); |
513
|
0
|
0
|
|
|
|
|
assert(loc != NULL); |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
} |
516
|
0
|
|
|
|
|
|
return loc; |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
|
519
|
0
|
|
|
|
|
|
void *psDynBufSubInit(psDynBuf_t *db, psDynBuf_t *sub, size_t capacity) |
520
|
|
|
|
|
|
|
{ |
521
|
0
|
|
|
|
|
|
void *mem = psDynBufAppendSize(db, capacity); |
522
|
|
|
|
|
|
|
|
523
|
0
|
0
|
|
|
|
|
if (mem) |
524
|
|
|
|
|
|
|
{ |
525
|
0
|
|
|
|
|
|
sub->buf.buf = db->buf.end - capacity; |
526
|
0
|
|
|
|
|
|
sub->buf.start = sub->buf.buf; |
527
|
0
|
|
|
|
|
|
sub->buf.end = sub->buf.buf; |
528
|
0
|
|
|
|
|
|
sub->buf.size = capacity; |
529
|
0
|
|
|
|
|
|
sub->pool = NULL; |
530
|
0
|
|
|
|
|
|
sub->master = db; |
531
|
0
|
|
|
|
|
|
sub->err = 0; |
532
|
|
|
|
|
|
|
#ifdef PSBUF_DEBUG_WITH_MEMSET |
533
|
|
|
|
|
|
|
memset(sub->buf.buf, '#', capacity); |
534
|
|
|
|
|
|
|
#endif /* PSBUF_DEBUG_WITH_MEMSET */ |
535
|
0
|
|
|
|
|
|
assert_subbuf(sub); |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
else |
538
|
|
|
|
|
|
|
{ |
539
|
0
|
|
|
|
|
|
sub->buf.buf = sub->buf.start = sub->buf.end = NULL; |
540
|
0
|
|
|
|
|
|
sub->buf.size = 0; |
541
|
0
|
|
|
|
|
|
sub->pool = NULL; |
542
|
0
|
|
|
|
|
|
sub->err = 1; |
543
|
0
|
|
|
|
|
|
db->err++; |
544
|
0
|
|
|
|
|
|
sub->master = db; |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
0
|
|
|
|
|
|
return mem; |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
|
550
|
0
|
|
|
|
|
|
void *psDynBufSubInitAt(psDynBuf_t *db, psDynBuf_t *sub, size_t at, |
551
|
|
|
|
|
|
|
size_t length) |
552
|
|
|
|
|
|
|
{ |
553
|
0
|
|
|
|
|
|
size_t len = db->buf.end - db->buf.start; |
554
|
|
|
|
|
|
|
|
555
|
0
|
0
|
|
|
|
|
if (db->err == 0 && at + length <= len) |
|
|
0
|
|
|
|
|
|
556
|
|
|
|
|
|
|
{ |
557
|
0
|
|
|
|
|
|
sub->buf.buf = db->buf.start + at; |
558
|
0
|
|
|
|
|
|
sub->buf.start = sub->buf.buf; |
559
|
0
|
|
|
|
|
|
sub->buf.end = sub->buf.buf; |
560
|
0
|
|
|
|
|
|
sub->buf.size = length; |
561
|
0
|
|
|
|
|
|
sub->pool = NULL; |
562
|
0
|
|
|
|
|
|
sub->master = db; |
563
|
0
|
|
|
|
|
|
sub->err = 0; |
564
|
|
|
|
|
|
|
#ifdef PSBUF_DEBUG_WITH_MEMSET |
565
|
|
|
|
|
|
|
memset(sub->buf.buf, '#', length); |
566
|
|
|
|
|
|
|
#endif /* PSBUF_DEBUG_WITH_MEMSET */ |
567
|
0
|
|
|
|
|
|
assert_subbuf(sub); |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
else |
570
|
|
|
|
|
|
|
{ |
571
|
0
|
|
|
|
|
|
sub->buf.buf = sub->buf.start = sub->buf.end = NULL; |
572
|
0
|
|
|
|
|
|
sub->buf.size = 0; |
573
|
0
|
|
|
|
|
|
sub->pool = NULL; |
574
|
0
|
|
|
|
|
|
sub->err++; |
575
|
0
|
|
|
|
|
|
db->err++; |
576
|
0
|
|
|
|
|
|
sub->master = db; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
0
|
|
|
|
|
|
return sub->buf.buf; |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
|
582
|
0
|
|
|
|
|
|
void *psDynBufSubFinish(psDynBuf_t *sub) |
583
|
|
|
|
|
|
|
{ |
584
|
0
|
|
|
|
|
|
void *loc = NULL; |
585
|
0
|
|
|
|
|
|
psDynBuf_t *db = sub->master; |
586
|
|
|
|
|
|
|
|
587
|
0
|
0
|
|
|
|
|
if (sub->err) |
588
|
|
|
|
|
|
|
{ |
589
|
0
|
|
|
|
|
|
db->err += sub->err; |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
else |
592
|
|
|
|
|
|
|
{ |
593
|
0
|
|
|
|
|
|
size_t total = sub->buf.size; |
594
|
0
|
|
|
|
|
|
size_t filled = sub->buf.end - sub->buf.start; |
595
|
|
|
|
|
|
|
size_t offset_tail; |
596
|
|
|
|
|
|
|
|
597
|
0
|
|
|
|
|
|
offset_tail = db->buf.end - (sub->buf.buf + sub->buf.size); |
598
|
|
|
|
|
|
|
|
599
|
0
|
|
|
|
|
|
assert_subbuf(sub); |
600
|
0
|
0
|
|
|
|
|
if (sub->buf.buf != sub->buf.start && filled > 0) |
|
|
0
|
|
|
|
|
|
601
|
|
|
|
|
|
|
{ |
602
|
0
|
|
|
|
|
|
memmove(sub->buf.buf, sub->buf.start, filled); |
603
|
|
|
|
|
|
|
} |
604
|
0
|
0
|
|
|
|
|
if (offset_tail > 0) |
605
|
|
|
|
|
|
|
{ |
606
|
0
|
|
|
|
|
|
memmove(db->buf.end - total + filled - offset_tail, |
607
|
0
|
|
|
|
|
|
db->buf.end - offset_tail, offset_tail); |
608
|
|
|
|
|
|
|
} |
609
|
0
|
|
|
|
|
|
db->buf.end -= total; |
610
|
0
|
|
|
|
|
|
db->buf.end += filled; |
611
|
0
|
|
|
|
|
|
loc = sub->buf.buf; |
612
|
|
|
|
|
|
|
} |
613
|
0
|
|
|
|
|
|
sub->buf.buf = NULL; |
614
|
0
|
|
|
|
|
|
psDynBufUninit(sub); |
615
|
0
|
|
|
|
|
|
return loc; |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
0
|
|
|
|
|
|
static size_t len_of_tag_and_len(size_t len) |
619
|
|
|
|
|
|
|
{ |
620
|
|
|
|
|
|
|
size_t lentaglen; |
621
|
|
|
|
|
|
|
|
622
|
0
|
0
|
|
|
|
|
if (len < 128) |
623
|
|
|
|
|
|
|
{ |
624
|
0
|
|
|
|
|
|
lentaglen = 2; |
625
|
|
|
|
|
|
|
} |
626
|
0
|
0
|
|
|
|
|
else if (len < 256) |
627
|
|
|
|
|
|
|
{ |
628
|
0
|
|
|
|
|
|
lentaglen = 3; |
629
|
|
|
|
|
|
|
} |
630
|
0
|
0
|
|
|
|
|
else if (len < 65536) |
631
|
|
|
|
|
|
|
{ |
632
|
0
|
|
|
|
|
|
lentaglen = 4; |
633
|
|
|
|
|
|
|
} |
634
|
0
|
0
|
|
|
|
|
else if (len < 16777216) |
635
|
|
|
|
|
|
|
{ |
636
|
0
|
|
|
|
|
|
lentaglen = 5; |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
else |
639
|
|
|
|
|
|
|
{ |
640
|
0
|
|
|
|
|
|
lentaglen = 6; /* Supports up-to 32-bit sizes. */ |
641
|
|
|
|
|
|
|
} |
642
|
0
|
|
|
|
|
|
return lentaglen; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
0
|
|
|
|
|
|
static void output_len(size_t len, unsigned char *target) |
646
|
|
|
|
|
|
|
{ |
647
|
0
|
0
|
|
|
|
|
if (len < 128) |
648
|
|
|
|
|
|
|
{ |
649
|
0
|
|
|
|
|
|
target[1] = (unsigned char) len; |
650
|
|
|
|
|
|
|
} |
651
|
0
|
0
|
|
|
|
|
else if (len < 256) |
652
|
|
|
|
|
|
|
{ |
653
|
0
|
|
|
|
|
|
target[1] = 0x81; |
654
|
0
|
|
|
|
|
|
target[2] = (unsigned char) len; |
655
|
|
|
|
|
|
|
} |
656
|
0
|
0
|
|
|
|
|
else if (len < 65536) |
657
|
|
|
|
|
|
|
{ |
658
|
0
|
|
|
|
|
|
target[1] = 0x82; |
659
|
0
|
|
|
|
|
|
target[2] = (unsigned char) (len >> 8); |
660
|
0
|
|
|
|
|
|
target[3] = (unsigned char) len; |
661
|
|
|
|
|
|
|
} |
662
|
0
|
0
|
|
|
|
|
else if (len < 16777216) |
663
|
|
|
|
|
|
|
{ |
664
|
0
|
|
|
|
|
|
target[1] = 0x83; |
665
|
0
|
|
|
|
|
|
target[2] = (unsigned char) (len >> 16); |
666
|
0
|
|
|
|
|
|
target[3] = (unsigned char) (len >> 8); |
667
|
0
|
|
|
|
|
|
target[4] = (unsigned char) len; |
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
else |
670
|
|
|
|
|
|
|
{ |
671
|
0
|
|
|
|
|
|
target[1] = 0x84; |
672
|
0
|
|
|
|
|
|
target[2] = (unsigned char) (len >> 24); |
673
|
0
|
|
|
|
|
|
target[3] = (unsigned char) (len >> 16); |
674
|
0
|
|
|
|
|
|
target[4] = (unsigned char) (len >> 8); |
675
|
0
|
|
|
|
|
|
target[5] = (unsigned char) len; |
676
|
|
|
|
|
|
|
} |
677
|
0
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
0
|
|
|
|
|
|
char *psDynBufAppendAsn1TagGen(psDynBuf_t *db, unsigned char tag, |
680
|
|
|
|
|
|
|
const unsigned char *bytes, size_t len) |
681
|
|
|
|
|
|
|
{ |
682
|
0
|
|
|
|
|
|
size_t extralen = len_of_tag_and_len(len); |
683
|
0
|
|
|
|
|
|
unsigned char *target = psDynBufAppendSize(db, len + extralen); |
684
|
|
|
|
|
|
|
|
685
|
0
|
0
|
|
|
|
|
if (target) |
686
|
|
|
|
|
|
|
{ |
687
|
0
|
|
|
|
|
|
target[0] = tag; |
688
|
0
|
|
|
|
|
|
output_len(len, target); |
689
|
0
|
|
|
|
|
|
memcpy(target + extralen, bytes, len); |
690
|
|
|
|
|
|
|
} |
691
|
0
|
|
|
|
|
|
return (char *) target; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
|
694
|
0
|
|
|
|
|
|
char *psDynBufBeginConstructedTag(psDynBuf_t *db, psDynBuf_t *sub) |
695
|
|
|
|
|
|
|
{ |
696
|
0
|
|
|
|
|
|
char *target = psDynBufSubInit(db, sub, 20); |
697
|
|
|
|
|
|
|
|
698
|
0
|
0
|
|
|
|
|
if (target) |
699
|
|
|
|
|
|
|
{ |
700
|
0
|
|
|
|
|
|
psDynBufReservePrepend(sub, 4); |
701
|
|
|
|
|
|
|
} |
702
|
0
|
|
|
|
|
|
return target; |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
|
705
|
0
|
|
|
|
|
|
char *psDynBufEndConstructedTag(psDynBuf_t *sub, unsigned char tag) |
706
|
|
|
|
|
|
|
{ |
707
|
0
|
|
|
|
|
|
size_t len = sub->buf.end - sub->buf.start; |
708
|
0
|
|
|
|
|
|
size_t extralen = len_of_tag_and_len(len); |
709
|
0
|
|
|
|
|
|
unsigned char *target = psDynBufPrependSize(sub, extralen); |
710
|
|
|
|
|
|
|
|
711
|
0
|
0
|
|
|
|
|
if (target) |
712
|
|
|
|
|
|
|
{ |
713
|
0
|
|
|
|
|
|
target[0] = tag; |
714
|
0
|
|
|
|
|
|
output_len(len, target); |
715
|
|
|
|
|
|
|
} |
716
|
0
|
|
|
|
|
|
psDynBufSubFinish(sub); |
717
|
0
|
|
|
|
|
|
return (char *) target; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
0
|
|
|
|
|
|
int32_t psParseBufFromStaticData(psParseBuf_t *pb, const void *data, size_t len) |
721
|
|
|
|
|
|
|
{ |
722
|
0
|
|
|
|
|
|
int32_t rc = psBufFromStaticData(&pb->buf, data, len); |
723
|
|
|
|
|
|
|
|
724
|
0
|
|
|
|
|
|
pb->pool = psStaticAllocationsPool; |
725
|
0
|
|
|
|
|
|
pb->err = rc != PS_SUCCESS; |
726
|
0
|
|
|
|
|
|
pb->master = NULL; |
727
|
0
|
|
|
|
|
|
return rc; |
728
|
|
|
|
|
|
|
} |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
/* The maximum supported PS_PARSE_MAXIMUM_TAG_CONTENT: */ |
731
|
|
|
|
|
|
|
#define PS_PARSE_MAXIMUM_TAG_CONTENT 0x40000000U /* 1 gigabyte. */ |
732
|
|
|
|
|
|
|
/* Note: If the value needs to be extended, the limit for function |
733
|
|
|
|
|
|
|
psParseBufGetTagLen() on 32-bit hosts is 0xFFFFFFFFU - 5. */ |
734
|
0
|
|
|
|
|
|
size_t psParseBufGetTagLen(const psParseBuf_t *pb, |
735
|
|
|
|
|
|
|
unsigned char tag, |
736
|
|
|
|
|
|
|
size_t *hdrLen_p) |
737
|
|
|
|
|
|
|
{ |
738
|
|
|
|
|
|
|
unsigned char lenlen; |
739
|
0
|
|
|
|
|
|
size_t len_at = 1; |
740
|
0
|
|
|
|
|
|
size_t len_hdr = 2; |
741
|
|
|
|
|
|
|
size_t len_content; |
742
|
|
|
|
|
|
|
size_t len_out; |
743
|
0
|
|
|
|
|
|
const unsigned char *ptr = pb->buf.start; |
744
|
0
|
|
|
|
|
|
size_t bytes = pb->buf.end - pb->buf.start; |
745
|
|
|
|
|
|
|
|
746
|
0
|
0
|
|
|
|
|
if (bytes < 2) |
747
|
|
|
|
|
|
|
{ |
748
|
0
|
|
|
|
|
|
return 0; |
749
|
|
|
|
|
|
|
} |
750
|
0
|
0
|
|
|
|
|
if (tag != 0 && ptr[0] != tag) |
|
|
0
|
|
|
|
|
|
751
|
|
|
|
|
|
|
{ |
752
|
0
|
|
|
|
|
|
return 0; |
753
|
|
|
|
|
|
|
} |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
/* Check size tag: long input lengths. */ |
756
|
0
|
|
|
|
|
|
lenlen = ptr[1]; /* Use lenlen temporarily to parse length field. */ |
757
|
0
|
0
|
|
|
|
|
if (lenlen >= 0x80) |
758
|
|
|
|
|
|
|
{ |
759
|
0
|
0
|
|
|
|
|
if (bytes < 0x83) |
760
|
|
|
|
|
|
|
{ |
761
|
0
|
|
|
|
|
|
return 0; |
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
|
764
|
0
|
0
|
|
|
|
|
if (lenlen == 0x81 && ptr[2] < 0x80) |
|
|
0
|
|
|
|
|
|
765
|
|
|
|
|
|
|
{ |
766
|
0
|
|
|
|
|
|
return 0; |
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
|
769
|
0
|
0
|
|
|
|
|
if (lenlen == 0x82 && ptr[2] == 0x00) |
|
|
0
|
|
|
|
|
|
770
|
|
|
|
|
|
|
{ |
771
|
0
|
|
|
|
|
|
return 0; |
772
|
|
|
|
|
|
|
} |
773
|
|
|
|
|
|
|
|
774
|
0
|
0
|
|
|
|
|
if (lenlen == 0x83 && ptr[2] == 0x00) |
|
|
0
|
|
|
|
|
|
775
|
|
|
|
|
|
|
{ |
776
|
0
|
|
|
|
|
|
return 0; |
777
|
|
|
|
|
|
|
} |
778
|
|
|
|
|
|
|
|
779
|
0
|
0
|
|
|
|
|
if (lenlen == 0x84 && ptr[2] == 0x00) |
|
|
0
|
|
|
|
|
|
780
|
|
|
|
|
|
|
{ |
781
|
0
|
|
|
|
|
|
return 0; |
782
|
|
|
|
|
|
|
} |
783
|
|
|
|
|
|
|
|
784
|
0
|
0
|
|
|
|
|
if (lenlen == 0x80 || lenlen > 0x84) |
|
|
0
|
|
|
|
|
|
785
|
|
|
|
|
|
|
{ |
786
|
0
|
|
|
|
|
|
return 0; /* Too large or indefinite len. */ |
787
|
|
|
|
|
|
|
} |
788
|
0
|
|
|
|
|
|
len_at++; |
789
|
0
|
|
|
|
|
|
lenlen -= 0x80; |
790
|
0
|
|
|
|
|
|
len_hdr += lenlen; |
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
else |
793
|
|
|
|
|
|
|
{ |
794
|
0
|
|
|
|
|
|
lenlen = 1; |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
/* len_at and lenlen now express length and of the len. */ |
798
|
|
|
|
|
|
|
/* additionally, its known that all the length bytes are accessible. */ |
799
|
0
|
|
|
|
|
|
len_content = 0; |
800
|
0
|
0
|
|
|
|
|
while (lenlen) |
801
|
|
|
|
|
|
|
{ |
802
|
0
|
|
|
|
|
|
len_content <<= 8; |
803
|
0
|
|
|
|
|
|
len_content += ptr[len_at]; |
804
|
0
|
|
|
|
|
|
len_at++; |
805
|
0
|
|
|
|
|
|
lenlen--; |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
|
808
|
0
|
0
|
|
|
|
|
if (len_content > PS_PARSE_MAXIMUM_TAG_CONTENT) |
809
|
|
|
|
|
|
|
{ |
810
|
0
|
|
|
|
|
|
return 0; |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
|
813
|
0
|
|
|
|
|
|
len_out = len_content + len_hdr; |
814
|
|
|
|
|
|
|
|
815
|
0
|
0
|
|
|
|
|
if (len_out > bytes) |
816
|
|
|
|
|
|
|
{ |
817
|
0
|
|
|
|
|
|
return 0; |
818
|
|
|
|
|
|
|
} |
819
|
|
|
|
|
|
|
|
820
|
0
|
0
|
|
|
|
|
if (hdrLen_p) |
821
|
|
|
|
|
|
|
{ |
822
|
0
|
|
|
|
|
|
*hdrLen_p = len_hdr; |
823
|
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
|
825
|
0
|
|
|
|
|
|
return len_out; |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
|
828
|
0
|
|
|
|
|
|
int psParseBufCanGetTag(const psParseBuf_t *pb, unsigned char tag) |
829
|
|
|
|
|
|
|
{ |
830
|
0
|
|
|
|
|
|
return psParseBufGetTagLen(pb, tag, NULL) > 0; |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
|
833
|
0
|
|
|
|
|
|
size_t psParseBufTrySkipBytes(psParseBuf_t *pb, |
834
|
|
|
|
|
|
|
const unsigned char *bytes, |
835
|
|
|
|
|
|
|
size_t numbytes) |
836
|
|
|
|
|
|
|
{ |
837
|
0
|
|
|
|
|
|
size_t skip_bytes = 0; |
838
|
|
|
|
|
|
|
|
839
|
0
|
0
|
|
|
|
|
if (psParseCanRead(pb, numbytes) && |
|
|
0
|
|
|
|
|
|
840
|
0
|
|
|
|
|
|
memcmp(bytes, pb->buf.start, numbytes) == 0) |
841
|
|
|
|
|
|
|
{ |
842
|
0
|
|
|
|
|
|
skip_bytes = numbytes; |
843
|
|
|
|
|
|
|
} |
844
|
0
|
|
|
|
|
|
pb->buf.start += skip_bytes; |
845
|
0
|
|
|
|
|
|
return skip_bytes; |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
0
|
|
|
|
|
|
size_t psParseBufSkipBytes(psParseBuf_t *pb, const unsigned char *bytes, |
849
|
|
|
|
|
|
|
size_t numbytes) |
850
|
|
|
|
|
|
|
{ |
851
|
0
|
|
|
|
|
|
size_t sz = psParseBufTrySkipBytes(pb, bytes, numbytes); |
852
|
|
|
|
|
|
|
|
853
|
0
|
0
|
|
|
|
|
if (sz == 0) |
854
|
|
|
|
|
|
|
{ |
855
|
0
|
|
|
|
|
|
pb->err++; |
856
|
|
|
|
|
|
|
} |
857
|
0
|
|
|
|
|
|
return sz; |
858
|
|
|
|
|
|
|
} |
859
|
|
|
|
|
|
|
|
860
|
0
|
|
|
|
|
|
size_t psParseBufTryReadTagSub(const psParseBuf_t *pb, |
861
|
|
|
|
|
|
|
psParseBuf_t *content, unsigned char tag) |
862
|
|
|
|
|
|
|
{ |
863
|
|
|
|
|
|
|
size_t hdrlen; |
864
|
0
|
|
|
|
|
|
size_t len = psParseBufGetTagLen(pb, tag, &hdrlen); |
865
|
|
|
|
|
|
|
size_t len_content; |
866
|
|
|
|
|
|
|
psParseBuf_t content_tmp; /* Allows calling the function with |
867
|
|
|
|
|
|
|
content == NULL to skip the tag. */ |
868
|
|
|
|
|
|
|
|
869
|
0
|
0
|
|
|
|
|
if (!content) |
870
|
|
|
|
|
|
|
{ |
871
|
0
|
|
|
|
|
|
content = &content_tmp; |
872
|
|
|
|
|
|
|
} |
873
|
0
|
0
|
|
|
|
|
if (!len) |
874
|
|
|
|
|
|
|
{ |
875
|
0
|
|
|
|
|
|
content->buf.buf = content->buf.start = content->buf.end = NULL; |
876
|
0
|
|
|
|
|
|
content->buf.size = 0; |
877
|
0
|
|
|
|
|
|
content->pool = NULL; |
878
|
|
|
|
|
|
|
/* Mark state of content as error. */ |
879
|
0
|
|
|
|
|
|
content->err = 1; |
880
|
|
|
|
|
|
|
/* Do not raise error status of main pb. */ |
881
|
0
|
|
|
|
|
|
content->master = (psParseBuf_t *) pb; |
882
|
0
|
|
|
|
|
|
return 0; |
883
|
|
|
|
|
|
|
} |
884
|
|
|
|
|
|
|
|
885
|
0
|
|
|
|
|
|
len_content = len - hdrlen; |
886
|
0
|
|
|
|
|
|
content->buf.start = content->buf.buf = pb->buf.start + hdrlen; |
887
|
0
|
|
|
|
|
|
content->buf.size = len_content; |
888
|
0
|
|
|
|
|
|
content->buf.end = content->buf.start + len_content; |
889
|
0
|
|
|
|
|
|
content->pool = NULL; |
890
|
0
|
|
|
|
|
|
content->master = (psParseBuf_t *) pb; |
891
|
0
|
|
|
|
|
|
content->err = 0; |
892
|
|
|
|
|
|
|
|
893
|
0
|
|
|
|
|
|
return len; |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
0
|
|
|
|
|
|
size_t psParseBufReadTagSub(psParseBuf_t *pb, |
897
|
|
|
|
|
|
|
psParseBuf_t *content, unsigned char tag) |
898
|
|
|
|
|
|
|
{ |
899
|
0
|
|
|
|
|
|
size_t len = psParseBufTryReadTagSub(pb, content, tag); |
900
|
|
|
|
|
|
|
|
901
|
0
|
0
|
|
|
|
|
if (len == 0) |
902
|
|
|
|
|
|
|
{ |
903
|
|
|
|
|
|
|
/* Mark this also as an error in main parse buffer. */ |
904
|
0
|
|
|
|
|
|
pb->err++; |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
/* Initialize sub as the same memory than main parse buffer, |
907
|
|
|
|
|
|
|
to allow parsing using it (typically unsuccessfully) |
908
|
|
|
|
|
|
|
in following parsing operations. */ |
909
|
0
|
|
|
|
|
|
memcpy(&(content->buf), &(pb->buf), sizeof content->buf); |
910
|
|
|
|
|
|
|
} |
911
|
0
|
|
|
|
|
|
return len; |
912
|
|
|
|
|
|
|
} |
913
|
|
|
|
|
|
|
|
914
|
0
|
|
|
|
|
|
size_t psParseBufReadTagRef(psParseBuf_t *pb, |
915
|
|
|
|
|
|
|
psBuf_t *ref, unsigned char tag) |
916
|
|
|
|
|
|
|
{ |
917
|
|
|
|
|
|
|
psParseBuf_t content; |
918
|
0
|
|
|
|
|
|
size_t len = psParseBufReadTagSub(pb, &content, tag); |
919
|
|
|
|
|
|
|
|
920
|
0
|
0
|
|
|
|
|
if (len) |
921
|
|
|
|
|
|
|
{ |
922
|
0
|
|
|
|
|
|
memcpy(ref, &content.buf, sizeof(psBuf_t)); |
923
|
0
|
|
|
|
|
|
pb->buf.start += len; |
924
|
|
|
|
|
|
|
} |
925
|
0
|
|
|
|
|
|
return len; |
926
|
|
|
|
|
|
|
} |
927
|
|
|
|
|
|
|
|
928
|
0
|
|
|
|
|
|
size_t psParseBufTrySkipTag(psParseBuf_t *pb, unsigned char tag) |
929
|
|
|
|
|
|
|
{ |
930
|
|
|
|
|
|
|
psParseBuf_t sub; |
931
|
0
|
|
|
|
|
|
size_t sz = psParseBufTryReadTagSub(pb, &sub, tag); |
932
|
|
|
|
|
|
|
|
933
|
0
|
0
|
|
|
|
|
if (sz) |
934
|
|
|
|
|
|
|
{ |
935
|
0
|
|
|
|
|
|
(void) psParseBufFinish(&sub); |
936
|
|
|
|
|
|
|
} |
937
|
0
|
|
|
|
|
|
return sz; |
938
|
|
|
|
|
|
|
} |
939
|
|
|
|
|
|
|
|
940
|
0
|
|
|
|
|
|
size_t psParseBufSkipTag(psParseBuf_t *pb, unsigned char tag) |
941
|
|
|
|
|
|
|
{ |
942
|
|
|
|
|
|
|
psParseBuf_t sub; |
943
|
0
|
|
|
|
|
|
size_t sz = psParseBufReadTagSub(pb, &sub, tag); |
944
|
|
|
|
|
|
|
|
945
|
0
|
0
|
|
|
|
|
if (sz) |
946
|
|
|
|
|
|
|
{ |
947
|
0
|
|
|
|
|
|
(void) psParseBufFinish(&sub); |
948
|
|
|
|
|
|
|
} |
949
|
0
|
|
|
|
|
|
return sz; |
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
|
952
|
0
|
|
|
|
|
|
int32_t psParseBufCopyAll(const psParseBuf_t *pb, unsigned char *target, |
953
|
|
|
|
|
|
|
size_t *targetlen) |
954
|
|
|
|
|
|
|
{ |
955
|
0
|
|
|
|
|
|
size_t len = pb->buf.end - pb->buf.start; |
956
|
|
|
|
|
|
|
|
957
|
0
|
0
|
|
|
|
|
if (pb->err != 0) |
958
|
|
|
|
|
|
|
{ |
959
|
0
|
|
|
|
|
|
return PS_FAILURE; |
960
|
|
|
|
|
|
|
} |
961
|
|
|
|
|
|
|
|
962
|
0
|
0
|
|
|
|
|
if (target == NULL) |
963
|
|
|
|
|
|
|
{ |
964
|
0
|
|
|
|
|
|
*targetlen = len; |
965
|
0
|
|
|
|
|
|
return PS_OUTPUT_LENGTH; |
966
|
|
|
|
|
|
|
} |
967
|
|
|
|
|
|
|
|
968
|
0
|
0
|
|
|
|
|
if (len > *targetlen) |
969
|
|
|
|
|
|
|
{ |
970
|
0
|
|
|
|
|
|
*targetlen = len; |
971
|
0
|
|
|
|
|
|
return PS_OUTPUT_LENGTH; |
972
|
|
|
|
|
|
|
} |
973
|
|
|
|
|
|
|
|
974
|
0
|
|
|
|
|
|
memcpy(target, pb->buf.start, len); |
975
|
0
|
|
|
|
|
|
*targetlen = len; |
976
|
0
|
|
|
|
|
|
return PS_SUCCESS; |
977
|
|
|
|
|
|
|
} |
978
|
|
|
|
|
|
|
|
979
|
0
|
|
|
|
|
|
int32_t psParseBufCopyN(const psParseBuf_t *pb, size_t reqLen, |
980
|
|
|
|
|
|
|
unsigned char *target, size_t *targetlen) |
981
|
|
|
|
|
|
|
{ |
982
|
0
|
|
|
|
|
|
size_t len = pb->buf.end - pb->buf.start; |
983
|
|
|
|
|
|
|
|
984
|
0
|
0
|
|
|
|
|
if (pb->err != 0) |
985
|
|
|
|
|
|
|
{ |
986
|
0
|
|
|
|
|
|
return PS_FAILURE; |
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
|
989
|
0
|
0
|
|
|
|
|
if (reqLen > len) |
990
|
|
|
|
|
|
|
{ |
991
|
0
|
|
|
|
|
|
reqLen = len; |
992
|
|
|
|
|
|
|
} |
993
|
|
|
|
|
|
|
|
994
|
0
|
0
|
|
|
|
|
if (target == NULL) |
995
|
|
|
|
|
|
|
{ |
996
|
0
|
|
|
|
|
|
*targetlen = reqLen; |
997
|
0
|
|
|
|
|
|
return PS_OUTPUT_LENGTH; |
998
|
|
|
|
|
|
|
} |
999
|
|
|
|
|
|
|
|
1000
|
0
|
0
|
|
|
|
|
if (reqLen > *targetlen) |
1001
|
|
|
|
|
|
|
{ |
1002
|
0
|
|
|
|
|
|
*targetlen = reqLen; |
1003
|
0
|
|
|
|
|
|
return PS_OUTPUT_LENGTH; |
1004
|
|
|
|
|
|
|
} |
1005
|
|
|
|
|
|
|
|
1006
|
0
|
|
|
|
|
|
memcpy(target, pb->buf.start, reqLen); |
1007
|
0
|
|
|
|
|
|
*targetlen = reqLen; |
1008
|
0
|
|
|
|
|
|
return PS_SUCCESS; |
1009
|
|
|
|
|
|
|
} |
1010
|
|
|
|
|
|
|
|
1011
|
0
|
|
|
|
|
|
int32_t psParseBufCopyUntilByte(psParseBuf_t *pb, unsigned char stopbyte, |
1012
|
|
|
|
|
|
|
unsigned char *target, size_t *targetlen) |
1013
|
|
|
|
|
|
|
{ |
1014
|
|
|
|
|
|
|
const unsigned char *end; |
1015
|
|
|
|
|
|
|
size_t len; |
1016
|
|
|
|
|
|
|
|
1017
|
0
|
0
|
|
|
|
|
if (pb->err != 0) |
1018
|
|
|
|
|
|
|
{ |
1019
|
0
|
|
|
|
|
|
return PS_FAILURE; |
1020
|
|
|
|
|
|
|
} |
1021
|
|
|
|
|
|
|
|
1022
|
0
|
|
|
|
|
|
end = memchr(pb->buf.start, stopbyte, pb->buf.end - pb->buf.start); |
1023
|
|
|
|
|
|
|
|
1024
|
0
|
0
|
|
|
|
|
if (end == NULL) |
1025
|
|
|
|
|
|
|
{ |
1026
|
0
|
|
|
|
|
|
return PS_FAILURE; |
1027
|
|
|
|
|
|
|
} |
1028
|
|
|
|
|
|
|
|
1029
|
0
|
|
|
|
|
|
len = (end - pb->buf.start) + 1; |
1030
|
0
|
|
|
|
|
|
return psParseBufCopyN(pb, len, target, targetlen); |
1031
|
|
|
|
|
|
|
} |
1032
|
|
|
|
|
|
|
|
1033
|
0
|
|
|
|
|
|
int psParseBufEq(const psParseBuf_t *pb1, const psParseBuf_t *pb2) |
1034
|
|
|
|
|
|
|
{ |
1035
|
0
|
0
|
|
|
|
|
if (pb1->err || pb2->err) |
|
|
0
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
{ |
1037
|
0
|
|
|
|
|
|
return 0; |
1038
|
|
|
|
|
|
|
} |
1039
|
|
|
|
|
|
|
|
1040
|
0
|
|
|
|
|
|
return psBufEq(&pb1->buf, &pb2->buf); |
1041
|
|
|
|
|
|
|
} |
1042
|
|
|
|
|
|
|
|
1043
|
0
|
|
|
|
|
|
int32_t psParseBufCheckState(const psParseBuf_t *pb) |
1044
|
|
|
|
|
|
|
{ |
1045
|
0
|
0
|
|
|
|
|
return pb->err == 0 ? PS_SUCCESS : PS_FAILURE; |
1046
|
|
|
|
|
|
|
} |
1047
|
|
|
|
|
|
|
|
1048
|
0
|
|
|
|
|
|
int32_t psParseBufFinish(psParseBuf_t *pb) |
1049
|
|
|
|
|
|
|
{ |
1050
|
|
|
|
|
|
|
int32_t rc; |
1051
|
|
|
|
|
|
|
|
1052
|
0
|
0
|
|
|
|
|
if (pb->master) |
1053
|
|
|
|
|
|
|
{ |
1054
|
0
|
0
|
|
|
|
|
if (pb->err) |
1055
|
|
|
|
|
|
|
{ |
1056
|
|
|
|
|
|
|
/* Signal master on error. */ |
1057
|
0
|
|
|
|
|
|
pb->master->err++; |
1058
|
|
|
|
|
|
|
} |
1059
|
|
|
|
|
|
|
else |
1060
|
|
|
|
|
|
|
{ |
1061
|
|
|
|
|
|
|
/* Advance master. */ |
1062
|
0
|
|
|
|
|
|
pb->master->buf.start = pb->buf.buf + pb->buf.size; |
1063
|
|
|
|
|
|
|
} |
1064
|
|
|
|
|
|
|
|
1065
|
0
|
|
|
|
|
|
pb->buf.buf = NULL; /* Do not free any data. */ |
1066
|
|
|
|
|
|
|
} |
1067
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
/* Free state. */ |
1069
|
0
|
|
|
|
|
|
rc = psParseBufCheckState(pb); |
1070
|
0
|
|
|
|
|
|
psBufUninit(pb->pool, &pb->buf); |
1071
|
0
|
|
|
|
|
|
pb->master = NULL; |
1072
|
0
|
|
|
|
|
|
pb->err = 0; |
1073
|
0
|
|
|
|
|
|
pb->pool = NULL; |
1074
|
0
|
|
|
|
|
|
return rc; |
1075
|
|
|
|
|
|
|
} |
1076
|
|
|
|
|
|
|
|
1077
|
0
|
|
|
|
|
|
void psParseBufCancel(psParseBuf_t *pb) |
1078
|
|
|
|
|
|
|
{ |
1079
|
|
|
|
|
|
|
/* Free state. */ |
1080
|
0
|
0
|
|
|
|
|
if (pb->master) |
1081
|
|
|
|
|
|
|
{ |
1082
|
0
|
|
|
|
|
|
pb->buf.buf = NULL; /* Do not free any data. */ |
1083
|
|
|
|
|
|
|
} |
1084
|
0
|
|
|
|
|
|
psBufUninit(pb->pool, &pb->buf); |
1085
|
0
|
|
|
|
|
|
pb->master = NULL; |
1086
|
0
|
|
|
|
|
|
pb->err = 0; |
1087
|
0
|
|
|
|
|
|
pb->pool = NULL; |
1088
|
0
|
|
|
|
|
|
} |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
/* end of file psbuf.c */ |