diff options
Diffstat (limited to 'source3/aparser/parser.c')
-rw-r--r-- | source3/aparser/parser.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/source3/aparser/parser.c b/source3/aparser/parser.c new file mode 100644 index 0000000000..0c7153e1fb --- /dev/null +++ b/source3/aparser/parser.c @@ -0,0 +1,471 @@ +#include "parser.h" + +/******************************************************************* + Attempt, if needed, to grow a data buffer. + Also depends on the data stream mode (io). + ********************************************************************/ + +BOOL io_grow(io_struct *ps, uint32 extra_space) +{ + uint32 new_size; + char *new_data; + + ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space); + + if(ps->data_offset + extra_space <= ps->buffer_size) + return True; + + /* + * We cannot grow the buffer if we're not reading + * into the io_struct, or if we don't own the memory. + */ + + if(UNMARSHALLING(ps) || !ps->is_dynamic) { + DEBUG(0,("io_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", + (unsigned int)extra_space)); + return False; + } + + /* + * Decide how much extra space we really need. + */ + + extra_space -= (ps->buffer_size - ps->data_offset); + if(ps->buffer_size == 0) { + new_size = extra_space; + + if((new_data = malloc(new_size)) == NULL) { + DEBUG(0,("io_grow: Malloc failure for size %u.\n", (unsigned int)new_size)); + return False; + } + memset(new_data, '\0', new_size ); + } else { + /* + * If the current buffer size is bigger than the space needed, just + * double it, else add extra_space. + */ + new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space); + + if ((new_data = Realloc(ps->data_p, new_size)) == NULL) { + DEBUG(0,("io_grow: Realloc failure for size %u.\n", + (unsigned int)new_size)); + return False; + } + } + ps->buffer_size = new_size; + ps->data_p = new_data; + + return True; +} + + +/******************************************************************* + Ensure we can read/write to a given offset. + ********************************************************************/ + +char *io_mem_get(io_struct *ps, uint32 extra_size) +{ + if(UNMARSHALLING(ps)) { + /* + * If reading, ensure that we can read the requested size item. + */ + if (ps->data_offset + extra_size > ps->buffer_size) { + DEBUG(0,("io_mem_get: reading data of size %u would overrun buffer.\n", + (unsigned int)extra_size )); + return NULL; + } + } else { + /* + * Writing - grow the buffer if needed. + */ + if(!io_grow(ps, extra_size)) + return False; + } + return &ps->data_p[ps->data_offset]; +} + +/******************************************************************* + Initialise a parse structure - malloc the data if requested. + ********************************************************************/ + +BOOL io_init(io_struct *ps, uint32 size, BOOL io) +{ + ZERO_STRUCTP(ps); + ps->io = io; + ps->bigendian_data = False; + ps->is_dynamic = False; + ps->data_offset = 0; + ps->buffer_size = 0; + ps->data_p = NULL; + + if (size != 0) { + ps->buffer_size = size; + if((ps->data_p = (char *)malloc((size_t)size)) == NULL) { + DEBUG(0,("io_init: malloc fail for %u bytes.\n", (unsigned int)size)); + return False; + } + ps->is_dynamic = True; /* We own this memory. */ + } + + return True; +} + +/******************************************************************* + debug output for parsing info. + + XXXX side-effect of this function is to increase the debug depth XXXX + + ********************************************************************/ +void io_debug(io_struct *ps, int depth, char *desc, char *fn_name) +{ + DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc)); +} + +/******************************************************************* + Align a the data_len to a multiple of align bytes - filling with + zeros. + ********************************************************************/ + +BOOL io_align2(io_struct *ps, int offset) +{ + uint32 mod = (ps->data_offset + offset) & (2-1); + + if (mod != 0) { + uint32 extra_space = (2 - mod); + if(!io_grow(ps, extra_space)) + return False; + memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); + ps->data_offset += extra_space; + } + + return True; +} + +BOOL io_align4(io_struct *ps, int offset) +{ + uint32 mod = (ps->data_offset + offset) & (4-1); + + if (mod != 0) { + uint32 extra_space = (4 - mod); + if(!io_grow(ps, extra_space)) + return False; + memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); + ps->data_offset += extra_space; + } + + return True; +} + +/******************************************************************* + Align a the data_len to a multiple of align bytes - filling with + zeros. + ********************************************************************/ + +BOOL io_align(io_struct *ps, int align) +{ + uint32 mod; + + if (!ps->autoalign) return True; + + mod = ps->data_offset & (align-1); + + if (align != 0 && mod != 0) { + uint32 extra_space = (align - mod); + if(!io_grow(ps, extra_space)) + return False; + memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space); + ps->data_offset += extra_space; + } + + return True; +} + + +/******************************************************************* + read from a socket into memory. + ********************************************************************/ +BOOL io_read(io_struct *ps, int fd, size_t len, int timeout) +{ + BOOL ok; + size_t prev_size = ps->buffer_size; + if (!io_grow(ps, len)) + { + return False; + } + + if (timeout > 0) + { + ok = (read(fd, &ps->data_p[prev_size], len) == len); + } + else + { + ok = (read(fd, &ps->data_p[prev_size], len) == len); + } + return ok; +} + + +/******************************************************************* + do IO on a uint32. + ********************************************************************/ +BOOL io_uint32(char *name, io_struct *ps, int depth, uint32 *data32, unsigned flags) +{ + char *q; + + if (!(flags & PARSE_SCALARS)) return True; + + if (!io_align(ps, 4)) return False; + + q = io_mem_get(ps, sizeof(uint32)); + if (q == NULL) return False; + + DBG_RW_IVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data32) + ps->data_offset += sizeof(uint32); + + return True; +} + +/******************************************************************* + do IO on a uint16. + ********************************************************************/ +BOOL io_uint16(char *name, io_struct *ps, int depth, uint16 *data16, unsigned flags) +{ + char *q; + + if (!(flags & PARSE_SCALARS)) return True; + + if (!io_align(ps, 2)) return False; + + q = io_mem_get(ps, sizeof(uint16)); + if (q == NULL) return False; + + DBG_RW_SVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data16) + ps->data_offset += sizeof(uint16); + + return True; +} + +/******************************************************************* + do IO on a uint8. + ********************************************************************/ +BOOL io_uint8(char *name, io_struct *ps, int depth, uint8 *data8, unsigned flags) +{ + char *q; + + if (!(flags & PARSE_SCALARS)) return True; + + q = io_mem_get(ps, sizeof(uint8)); + if (q == NULL) return False; + + DBG_RW_IVAL(name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, *data8) + ps->data_offset += sizeof(uint8); + + return True; +} + +/******************************************************************* + do IO on a pointer + ********************************************************************/ +BOOL io_pointer(char *desc, io_struct *ps, int depth, void **p, unsigned flags) +{ + uint32 v; + + if (!(flags & PARSE_SCALARS)) return True; + + v = (*p) ? 0xdeadbeef : 0; + if (!io_uint32(desc, ps, depth, &v, flags)) return False; + *p = (void *) (v ? 0xdeadbeef : 0); + return True; +} + +/******************************************************************* + Stream a null-terminated string. + ********************************************************************/ +BOOL io_SMBSTR(char *name, io_struct *ps, int depth, char **str, unsigned flags) +{ + char *q; + uint8 *start; + int i; + size_t len; + int start_offset = ps->data_offset; + + if (!(flags & PARSE_SCALARS)) return True; + + if (UNMARSHALLING(ps)) { + *str = io_mem_get(ps, 0); + if (*str == NULL) + return False; + len = strlen(*str); + ps->data_offset += len + 1; + } + else + { + len = strlen(*str)+1; + start = (uint8*)q; + + for(i = 0; i < len; i++) { + q = io_mem_get(ps, 1); + if (q == NULL) + return False; + + RW_CVAL(ps->io, q, (*str)[i],0); + ps->data_offset++; + } + } + + DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), + start_offset, name, *str)); + return True; +} + +/****************************************************************** + do IO on a byte array + ********************************************************************/ +BOOL io_uint8s(char *name, io_struct *ps, int depth, uint8 **data8s, int len, unsigned flags) +{ + char *q; + size_t num_bytes = len * sizeof(uint8); + + if (!(flags & PARSE_SCALARS)) return True; + + q = io_mem_get(ps, num_bytes); + if (q == NULL) return False; + + if (MARSHALLING(ps)) + { + DBG_RW_PCVAL(True, name, depth, ps->data_offset, ps->io, q, *data8s, len) + } + else + { + *data8s = q; + dump_data(depth+5, *data8s, num_bytes); + } + ps->data_offset += num_bytes; + + return True; +} +/****************************************************************** + do IO on a fixed-size byte array + ********************************************************************/ +BOOL io_uint8s_fixed(char *name, io_struct *ps, int depth, uint8 *data8s, int len, unsigned flags) +{ + char *q; + size_t num_bytes = len * sizeof(uint8); + + if (!(flags & PARSE_SCALARS)) return True; + + q = io_mem_get(ps, num_bytes); + if (q == NULL) return False; + + DBG_RW_PCVAL(True, name, depth, ps->data_offset, ps->io, q, data8s, len) + ps->data_offset += num_bytes; + + return True; +} + + +/****************************************************************** + do IO on an io (eh?? :) + ********************************************************************/ +BOOL io_io_struct(char *name, io_struct *ps, int depth, io_struct *io, unsigned flags) +{ + char *q; + uint16 len; + + if (!(flags & PARSE_SCALARS)) return True; + + q = io_mem_get(ps, sizeof(uint16)); + if (q == NULL) return False; + + /* length first */ + if (MARSHALLING(ps)) + { + len = io->data_offset; + } + if (!io_uint16("len", ps, depth+1, &len, flags)) + { + return False; + } + if (UNMARSHALLING(ps)) + { + if (!io_init(io, len, UNMARSHALL)) + { + return False; + } + } + + /* now data */ + q = io_mem_get(ps, len * sizeof(uint8)); + if (q == NULL) return False; + + if (MARSHALLING(ps)) + { + DBG_RW_PCVAL(False, name, depth+1, ps->data_offset, ps->io, q, io->data_p, len) + } + else + { + io->data_p = q; + dump_data(depth+5, q, len); + } + ps->data_offset += len; + + return True; +} + +/****************************************************************** + do IO on a unicode array + ********************************************************************/ +BOOL io_wstring(char *name, io_struct *ps, int depth, uint16 *data16s, int len, unsigned flags) +{ + char *q; + + if (!(flags & PARSE_SCALARS)) return True; + + if (!io_align(ps, 2)) return False; + + q = io_mem_get(ps, len * sizeof(uint16)); + if (q == NULL) return False; + + DBG_RW_PSVAL(True, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data16s, len) + ps->data_offset += (len * sizeof(uint16)); + + return True; +} + + +/****************************************************************** +allocate some memory for a parse structure + ********************************************************************/ +void io_free(io_struct *ps) +{ + if (ps->is_dynamic && ps->data_p) + { + free(ps->data_p); + ps->data_p = NULL; + } +} + +/****************************************************************** +allocate some memory for a parse structure + ********************************************************************/ +BOOL io_alloc(char *name, io_struct *ps, void **ptr, unsigned size) +{ + (*ptr) = (void *)malloc(size); + if (*ptr) return True; + return False; +} + +/****************************************************************** +realloc some memory for a parse structure + ********************************************************************/ +BOOL io_realloc(char *name, io_struct *ps, void **ptr, unsigned size) +{ + BOOL ret = True; + void *tp; + + tp = (void *)Realloc(*ptr, size); + if (tp) *ptr = tp; + else ret = False; + return ret; +} + |