s3:smbd: fix NULL dereference in case of readlink failure
[Samba.git] / source3 / registry / reg_parse_prs.c
blob8daa7d90d42561e31108d96e963c5141e2a77e3b
1 /*
2 Unix SMB/CIFS implementation.
3 Samba memory buffer functions
4 Copyright (C) Andrew Tridgell 1992-1997
5 Copyright (C) Luke Kenneth Casson Leighton 1996-1997
6 Copyright (C) Jeremy Allison 1999
7 Copyright (C) Andrew Bartlett 2003.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "reg_parse_prs.h"
25 #include "rpc_dce.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_PARSE
30 static const char *tab_depth(int level, int depth)
32 if( CHECK_DEBUGLVL(level) ) {
33 dbgtext("%*s", depth*4, "");
35 return "";
38 /*******************************************************************
39 Debug output for parsing info
41 XXXX side-effect of this function is to increase the debug depth XXXX.
43 ********************************************************************/
45 void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name)
47 DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(5+depth,depth), ps->data_offset, fn_name, desc));
50 /**
51 * Initialise an expandable parse structure.
53 * @param size Initial buffer size. If >0, a new buffer will be
54 * created with talloc().
56 * @return False if allocation fails, otherwise True.
57 **/
59 bool prs_init(prs_struct *ps, uint32_t size, TALLOC_CTX *ctx, bool io)
61 ZERO_STRUCTP(ps);
62 ps->io = io;
63 ps->bigendian_data = RPC_LITTLE_ENDIAN;
64 ps->align = RPC_PARSE_ALIGN;
65 ps->is_dynamic = False;
66 ps->data_offset = 0;
67 ps->buffer_size = 0;
68 ps->data_p = NULL;
69 ps->mem_ctx = ctx;
71 if (size != 0) {
72 ps->buffer_size = size;
73 ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, size);
74 if(ps->data_p == NULL) {
75 DEBUG(0,("prs_init: talloc fail for %u bytes.\n", (unsigned int)size));
76 return False;
78 ps->is_dynamic = True; /* We own this memory. */
79 } else if (MARSHALLING(ps)) {
80 /* If size is zero and we're marshalling we should allocate memory on demand. */
81 ps->is_dynamic = True;
84 return True;
87 /*******************************************************************
88 Delete the memory in a parse structure - if we own it.
90 NOTE: Contrary to the somewhat confusing naming, this function is not
91 intended for freeing memory allocated by prs_alloc_mem().
92 That memory is also attached to the talloc context given by
93 ps->mem_ctx, but is only freed when that talloc context is
94 freed. prs_mem_free() is used to delete "dynamic" memory
95 allocated in marshalling/unmarshalling.
96 ********************************************************************/
98 void prs_mem_free(prs_struct *ps)
100 if(ps->is_dynamic) {
101 TALLOC_FREE(ps->data_p);
103 ps->is_dynamic = False;
104 ps->buffer_size = 0;
105 ps->data_offset = 0;
108 /*******************************************************************
109 Allocate memory when unmarshalling... Always zero clears.
110 ********************************************************************/
112 #if defined(PARANOID_MALLOC_CHECKER)
113 char *prs_alloc_mem_(prs_struct *ps, size_t size, unsigned int count)
114 #else
115 char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count)
116 #endif
118 char *ret = NULL;
120 if (size && count) {
121 /* We can't call the type-safe version here. */
122 ret = (char *)_talloc_zero_array(ps->mem_ctx, size, count,
123 "parse_prs");
125 return ret;
128 /*******************************************************************
129 Return the current talloc context we're using.
130 ********************************************************************/
132 TALLOC_CTX *prs_get_mem_context(prs_struct *ps)
134 return ps->mem_ctx;
137 /*******************************************************************
138 Attempt, if needed, to grow a data buffer.
139 Also depends on the data stream mode (io).
140 ********************************************************************/
142 bool prs_grow(prs_struct *ps, uint32_t extra_space)
144 uint32_t new_size;
146 ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
148 if(ps->data_offset + extra_space <= ps->buffer_size)
149 return True;
152 * We cannot grow the buffer if we're not reading
153 * into the prs_struct, or if we don't own the memory.
156 if(UNMARSHALLING(ps) || !ps->is_dynamic) {
157 DEBUG(0,("prs_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
158 (unsigned int)extra_space));
159 return False;
163 * Decide how much extra space we really need.
166 extra_space -= (ps->buffer_size - ps->data_offset);
167 if(ps->buffer_size == 0) {
170 * Start with 128 bytes (arbitrary value), enough for small rpc
171 * requests
173 new_size = MAX(128, extra_space);
175 ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, new_size);
176 if(ps->data_p == NULL) {
177 DEBUG(0,("prs_grow: talloc failure for size %u.\n", (unsigned int)new_size));
178 return False;
180 } else {
182 * If the current buffer size is bigger than the space needed,
183 * just double it, else add extra_space. Always keep 64 bytes
184 * more, so that after we added a large blob we don't have to
185 * realloc immediately again.
187 new_size = MAX(ps->buffer_size*2,
188 ps->buffer_size + extra_space + 64);
190 ps->data_p = talloc_realloc(ps->mem_ctx,
191 ps->data_p,
192 char,
193 new_size);
194 if (ps->data_p == NULL) {
195 DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
196 (unsigned int)new_size));
197 return False;
200 memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
202 ps->buffer_size = new_size;
204 return True;
207 /*******************************************************************
208 Get the data pointer (external interface).
209 ********************************************************************/
211 char *prs_data_p(prs_struct *ps)
213 return ps->data_p;
216 /*******************************************************************
217 Get the current data size (external interface).
218 ********************************************************************/
220 uint32_t prs_data_size(prs_struct *ps)
222 return ps->buffer_size;
225 /*******************************************************************
226 Fetch the current offset (external interface).
227 ********************************************************************/
229 uint32_t prs_offset(prs_struct *ps)
231 return ps->data_offset;
234 /*******************************************************************
235 Set the current offset (external interface).
236 ********************************************************************/
238 bool prs_set_offset(prs_struct *ps, uint32_t offset)
240 if ((offset > ps->data_offset)
241 && !prs_grow(ps, offset - ps->data_offset)) {
242 return False;
245 ps->data_offset = offset;
246 return True;
249 /*******************************************************************
250 Append the data from a buffer into a parse_struct.
251 ********************************************************************/
253 bool prs_copy_data_in(prs_struct *dst, const char *src, uint32_t len)
255 if (len == 0)
256 return True;
258 if(!prs_grow(dst, len))
259 return False;
261 memcpy(&dst->data_p[dst->data_offset], src, (size_t)len);
262 dst->data_offset += len;
264 return True;
267 /*******************************************************************
268 Align the data_len to a multiple of align bytes - filling with
269 zeros.
270 ********************************************************************/
272 bool prs_align(prs_struct *ps)
274 uint32_t mod = ps->data_offset & (ps->align-1);
276 if (ps->align != 0 && mod != 0) {
277 uint32_t extra_space = (ps->align - mod);
278 if(!prs_grow(ps, extra_space))
279 return False;
280 memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
281 ps->data_offset += extra_space;
284 return True;
287 /******************************************************************
288 Align on a 8 byte boundary
289 *****************************************************************/
291 bool prs_align_uint64(prs_struct *ps)
293 bool ret;
294 uint8_t old_align = ps->align;
296 ps->align = 8;
297 ret = prs_align(ps);
298 ps->align = old_align;
300 return ret;
303 /*******************************************************************
304 Ensure we can read/write to a given offset.
305 ********************************************************************/
307 char *prs_mem_get(prs_struct *ps, uint32_t extra_size)
309 if(UNMARSHALLING(ps)) {
311 * If reading, ensure that we can read the requested size item.
313 if (ps->data_offset + extra_size > ps->buffer_size) {
314 DEBUG(0,("prs_mem_get: reading data of size %u would overrun "
315 "buffer by %u bytes.\n",
316 (unsigned int)extra_size,
317 (unsigned int)(ps->data_offset + extra_size - ps->buffer_size) ));
318 return NULL;
320 } else {
322 * Writing - grow the buffer if needed.
324 if(!prs_grow(ps, extra_size))
325 return NULL;
327 return &ps->data_p[ps->data_offset];
330 /*******************************************************************
331 Change the struct type.
332 ********************************************************************/
334 void prs_switch_type(prs_struct *ps, bool io)
336 if ((ps->io ^ io) == True)
337 ps->io=io;
340 /*******************************************************************
341 Stream a uint16.
342 ********************************************************************/
344 bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16_t *data16)
346 char *q = prs_mem_get(ps, sizeof(uint16_t));
347 if (q == NULL)
348 return False;
350 if (UNMARSHALLING(ps)) {
351 if (ps->bigendian_data)
352 *data16 = RSVAL(q,0);
353 else
354 *data16 = SVAL(q,0);
355 } else {
356 if (ps->bigendian_data)
357 RSSVAL(q,0,*data16);
358 else
359 SSVAL(q,0,*data16);
362 DEBUGADD(5,("%s%04x %s: %04x\n", tab_depth(5,depth), ps->data_offset, name, *data16));
364 ps->data_offset += sizeof(uint16_t);
366 return True;
369 /*******************************************************************
370 Stream a uint32.
371 ********************************************************************/
373 bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32_t *data32)
375 char *q = prs_mem_get(ps, sizeof(uint32_t));
376 if (q == NULL)
377 return False;
379 if (UNMARSHALLING(ps)) {
380 if (ps->bigendian_data)
381 *data32 = RIVAL(q,0);
382 else
383 *data32 = IVAL(q,0);
384 } else {
385 if (ps->bigendian_data)
386 RSIVAL(q,0,*data32);
387 else
388 SIVAL(q,0,*data32);
391 DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32));
393 ps->data_offset += sizeof(uint32_t);
395 return True;
398 /*******************************************************************
399 Stream a uint64_struct
400 ********************************************************************/
401 bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64_t *data64)
403 if (UNMARSHALLING(ps)) {
404 uint32_t high, low;
406 if (!prs_uint32(name, ps, depth+1, &low))
407 return False;
409 if (!prs_uint32(name, ps, depth+1, &high))
410 return False;
412 *data64 = ((uint64_t)high << 32) + low;
414 return True;
415 } else {
416 uint32_t high = (*data64) >> 32, low = (*data64) & 0xFFFFFFFF;
417 return prs_uint32(name, ps, depth+1, &low) &&
418 prs_uint32(name, ps, depth+1, &high);
422 /******************************************************************
423 Stream an array of uint8s. Length is number of uint8s.
424 ********************************************************************/
426 bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8_t *data8s, int len)
428 int i;
429 char *q = prs_mem_get(ps, len);
430 if (q == NULL)
431 return False;
433 if (UNMARSHALLING(ps)) {
434 for (i = 0; i < len; i++)
435 data8s[i] = CVAL(q,i);
436 } else {
437 for (i = 0; i < len; i++)
438 SCVAL(q, i, data8s[i]);
441 DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset ,name));
442 if (charmode)
443 print_asc(5, (unsigned char*)data8s, len);
444 else {
445 for (i = 0; i < len; i++)
446 DEBUGADD(5,("%02x ", data8s[i]));
448 DEBUGADD(5,("\n"));
450 ps->data_offset += len;
452 return True;