/* - allocset - allocate a set of characters for [] */ static cset * allocset(struct parse *p) { int no = p->g->ncsets++; size_t nc; size_t nbytes; cset *cs; size_t css = (size_t)p->g->csetsize; int i; if (no >= p->ncsalloc) { /* need another column of space */ void *ptr; p->ncsalloc += CHAR_BIT; nc = p->ncsalloc; assert(nc % CHAR_BIT == 0); nbytes = nc / CHAR_BIT * css; ptr = (cset *)cli_realloc((char *)p->g->sets, nc * sizeof(cset)); if (ptr == NULL) goto nomem; p->g->sets = ptr; ptr = (uch *)cli_realloc((char *)p->g->setbits, nbytes); if (ptr == NULL) goto nomem; p->g->setbits = ptr; for (i = 0; i < no; i++) p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); } /* XXX should not happen */ if (p->g->sets == NULL || p->g->setbits == NULL) goto nomem; cs = &p->g->sets[no]; cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); cs->mask = 1 << ((no) % CHAR_BIT); cs->hash = 0; cs->smultis = 0; cs->multis = NULL; return(cs); nomem: free(p->g->sets); p->g->sets = NULL; free(p->g->setbits); p->g->setbits = NULL; SETERROR(REG_ESPACE); /* caller's responsibility not to do set ops */ return(NULL); }
static void init_testfiles(void) { struct dirent *dirent; unsigned i = 0; int expect = expected_testfiles; DIR *d = opendir(OBJDIR"/../test"); fail_unless(!!d, "opendir"); if (!d) return; testfiles = NULL; testfiles_n = 0; while ((dirent = readdir(d))) { if (strncmp(dirent->d_name, "clam", 4)) continue; i++; testfiles = cli_realloc(testfiles, i*sizeof(*testfiles)); fail_unless(!!testfiles, "cli_realloc"); testfiles[i-1] = strdup(dirent->d_name); } testfiles_n = i; if (get_fpu_endian() == FPU_ENDIAN_UNKNOWN) expect--; expect -= skip_files(); fail_unless_fmt(testfiles_n == expect, "testfiles: %d != %d", testfiles_n, expect); closedir(d); }
/* * Return clamav return code */ int blobGrow(blob *b, size_t len) { assert(b != NULL); assert(b->magic == BLOBCLASS); if(len == 0) return CL_SUCCESS; if(b->isClosed) { /* * Should be cli_dbgmsg, but I want to see them for now, * and cli_dbgmsg doesn't support debug levels */ cli_warnmsg("Growing closed blob\n"); b->isClosed = 0; } if(b->data == NULL) { assert(b->len == 0); assert(b->size == 0); b->data = cli_malloc(len); if(b->data) b->size = (off_t)len; } else { unsigned char *ptr = cli_realloc(b->data, b->size + len); if(ptr) { b->size += (off_t)len; b->data = ptr; } } return (b->data) ? CL_SUCCESS : CL_EMEM; }
static void textbuf_clean(struct text_buffer *buf) { if(buf->capacity > BUF_KEEP_SIZE) { buf->data = cli_realloc(buf->data, BUF_KEEP_SIZE); buf->capacity = BUF_KEEP_SIZE; } buf->pos = 0; }
/* - stripsnug - compact the strip */ static void stripsnug(struct parse *p, struct re_guts *g) { g->nstates = p->slen; g->strip = (sop *)cli_realloc((char *)p->strip, p->slen * sizeof(sop)); if (g->strip == NULL) { SETERROR(REG_ESPACE); g->strip = p->strip; } }
static inline char *textbuffer_done(yyscan_t scanner) { char *str = cli_realloc(scanner->buf.data, scanner->buf.pos); if(!str) { str = scanner->buf.data; } scanner->yytext = str; scanner->yylen = scanner->buf.pos - 1; memset(&scanner->buf, 0, sizeof(scanner->buf)); return str; }
static int tokens_ensure_capacity(struct tokens *tokens, size_t cap) { if(tokens->capacity < cap) { cap += 1024; tokens->data = cli_realloc(tokens->data, cap * sizeof(*tokens->data)); if(!tokens->data) return CL_EMEM; tokens->capacity = cap; } return CL_SUCCESS; }
static char * get_unicode_name(const char *name, int size, int big_endian) { int i, increment; char *newname, *ret; if((name == NULL) || (*name == '\0') || (size <= 0)) return NULL; newname = (char *)cli_malloc(size * 7 + 1); if(newname == NULL) { cli_errmsg("get_unicode_name: Unable to allocate memory for newname\n"); return NULL; } if((!big_endian) && (size & 0x1)) { cli_dbgmsg("get_unicode_name: odd number of bytes %d\n", size); --size; } increment = (big_endian) ? 1 : 2; ret = newname; for(i = 0; i < size; i += increment) { if((!(name[i]&0x80)) && isprint(name[i])) { *ret++ = tolower(name[i]); } else { if((name[i] < 10) && (name[i] >= 0)) { *ret++ = '_'; *ret++ = (char)(name[i] + '0'); } else { uint16_t x; if ((i + 1) >= size) break; x = (uint16_t)((name[i] << 8) | name[i + 1]); *ret++ = '_'; *ret++ = (char)('a'+((x&0xF))); *ret++ = (char)('a'+((x>>4)&0xF)); *ret++ = (char)('a'+((x>>8)&0xF)); *ret++ = 'a'; *ret++ = 'a'; } *ret++ = '_'; } } *ret = '\0'; /* Saves a lot of memory */ ret = cli_realloc(newname, (ret - newname) + 1); return ret ? ret : newname; }
static int tokens_ensure_capacity(struct tokens *tokens, size_t cap) { if(tokens->capacity < cap) { yystype *data; cap += 1024; /* Keep old data if OOM */ data = cli_realloc(tokens->data, cap * sizeof(*tokens->data)); if(!data) return CL_EMEM; tokens->data = data; tokens->capacity = cap; } return CL_SUCCESS; }
static inline void ev_chain(cli_events_t *ctx, struct cli_event *ev, union ev_val *val) { union ev_val *chain; uint32_t siz = sizeof(*chain) * (ev->count + 1); chain = cli_realloc(ev->u.v_chain, siz); if (!chain) { cli_event_error_oom(ctx, siz); return; } ev->u.v_chain = chain; ev->u.v_chain[ev->count] = *val; ev->count++; }
int32_t cli_bcapi_hashset_new(struct cli_bc_ctx *ctx ) { unsigned n = ctx->nhashsets+1; struct cli_hashset *s = cli_realloc(ctx->hashsets, sizeof(*ctx->hashsets)*n); if (!s) { cli_event_error_oom(EV, 0); return -1; } ctx->hashsets = s; ctx->nhashsets = n; s = &s[n-1]; cli_hashset_init(s, 16, 80); return n-1; }
/* - enlarge - enlarge the strip */ static void enlarge(struct parse *p, sopno size) { sop *sp; if (p->ssize >= size) return; sp = (sop *)cli_realloc(p->strip, size*sizeof(sop)); if (sp == NULL) { SETERROR(REG_ESPACE); return; } p->strip = sp; p->ssize = size; }
static int onas_ddd_grow_wdlt() { char **ptr = NULL; ptr = (char **) cli_realloc(wdlt, wdlt_len << 1); if (ptr) { wdlt = ptr; memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1)); } else { return CL_EMEM; } wdlt_len <<= 1; return CL_SUCCESS; }
int32_t cli_bcapi_inflate_init(struct cli_bc_ctx *ctx, int32_t from, int32_t to, int32_t windowBits) { int ret; z_stream stream; struct bc_inflate *b; unsigned n = ctx->ninflates + 1; if (!get_buffer(ctx, from) || !get_buffer(ctx, to)) { cli_dbgmsg("bytecode api: inflate_init: invalid buffers!\n"); return -1; } memset(&stream, 0, sizeof(stream)); ret = inflateInit2(&stream, windowBits); switch (ret) { case Z_MEM_ERROR: cli_dbgmsg("bytecode api: inflateInit2: out of memory!\n"); return -1; case Z_VERSION_ERROR: cli_dbgmsg("bytecode api: inflateinit2: zlib version error!\n"); return -1; case Z_STREAM_ERROR: cli_dbgmsg("bytecode api: inflateinit2: zlib stream error!\n"); return -1; case Z_OK: break; default: cli_dbgmsg("bytecode api: inflateInit2: unknown error %d\n", ret); return -1; } b = cli_realloc(ctx->inflates, sizeof(*ctx->inflates)*n); if (!b) { inflateEnd(&stream); return -1; } ctx->inflates = b; ctx->ninflates = n; b = &b[n-1]; b->from = from; b->to = to; b->needSync = 0; memcpy(&b->stream, &stream, sizeof(stream)); return n-1; }
/* - mcadd - add a collating element to a cset */ static void mcadd( struct parse *p, cset *cs, const char *cp) { size_t oldend = cs->smultis; void *np; cs->smultis += strlen(cp) + 1; np = cli_realloc(cs->multis, cs->smultis); if (np == NULL) { if (cs->multis) free(cs->multis); cs->multis = NULL; SETERROR(REG_ESPACE); return; } cs->multis = np; cli_strlcpy(cs->multis + oldend - 1, cp, cs->smultis - oldend + 1); }
int32_t cli_bcapi_hashset_done(struct cli_bc_ctx *ctx , int32_t id) { struct cli_hashset *s = get_hashset(ctx, id); if (!s) return -1; cli_hashset_destroy(s); if (id == ctx->nhashsets-1) { ctx->nhashsets--; if (!ctx->nhashsets) { free(ctx->hashsets); ctx->hashsets = NULL; } else { s = cli_realloc(ctx->hashsets, ctx->nhashsets*sizeof(*s)); if (s) ctx->hashsets = s; } } return 0; }
int32_t cli_bcapi_buffer_pipe_new(struct cli_bc_ctx *ctx, uint32_t size) { unsigned char *data; struct bc_buffer *b; unsigned n = ctx->nbuffers + 1; data = cli_calloc(1, size); if (!data) return -1; b = cli_realloc(ctx->buffers, sizeof(*ctx->buffers)*n); if (!b) { free(data); return -1; } ctx->buffers = b; ctx->nbuffers = n; b = &b[n-1]; b->data = data; b->size = size; b->write_cursor = b->read_cursor = 0; return n-1; }
int32_t cli_bcapi_buffer_pipe_new_fromfile(struct cli_bc_ctx *ctx , uint32_t at) { struct bc_buffer *b; unsigned n = ctx->nbuffers + 1; if (at >= ctx->file_size) return -1; b = cli_realloc(ctx->buffers, sizeof(*ctx->buffers)*n); if (!b) { return -1; } ctx->buffers = b; ctx->nbuffers = n; b = &b[n-1]; /* NULL data means read from file at pos read_cursor */ b->data = NULL; b->size = 0; b->read_cursor = at; b->write_cursor = 0; return n-1; }
void blobClose(blob *b) { assert(b != NULL); assert(b->magic == BLOBCLASS); if(b->isClosed) { cli_warnmsg("Attempt to close a previously closed blob\n"); return; } /* * Nothing more is going to be added to this blob. If it'll save more * than a trivial amount (say 64 bytes) of memory, shrink the allocation */ if((b->size - b->len) >= 64) { if(b->len == 0) { /* Not likely */ free(b->data); b->data = NULL; cli_dbgmsg("blobClose: recovered all %lu bytes\n", (unsigned long)b->size); b->size = 0; } else { unsigned char *ptr = cli_realloc(b->data, b->len); if(ptr == NULL) return; cli_dbgmsg("blobClose: recovered %lu bytes from %lu\n", (unsigned long)(b->size - b->len), (unsigned long)b->size); b->size = b->len; b->data = ptr; } } b->isClosed = 1; }
/* buffer is html-normlike "chunk", if original file is bigger than buffer, * we rewind to a space, so we'll know that tokens won't be broken in half at * the end of a buffer. All tokens except string-literals of course. * So we can assume that after the buffer there is either a space, EOF, or a * chunk of text not containing whitespace at all (for which we care only if its * a stringliteral)*/ void cli_js_process_buffer(struct parser_state *state, const char *buf, size_t n) { struct scope* current = state->current; YYSTYPE val; int yv; YY_BUFFER_STATE yyb; if(!state->global) { /* this state has either not been initialized, * or cli_js_parse_done() was already called on it */ cli_warnmsg(MODULE "invalid state\n"); return; } yyb = yy_scan_bytes(buf, n, state->scanner); memset(&val, 0, sizeof(val)); val.vtype = vtype_undefined; /* on EOF yylex will return 0 */ while( (yv=yylex(&val, state->scanner)) != 0) { const char *text; size_t leng; val.type = yv; switch(yv) { case TOK_VAR: current->fsm_state = InsideVar; break; case TOK_IDENTIFIER_NAME: text = yyget_text(state->scanner); leng = yyget_leng(state->scanner); if(current->last_token == TOK_DOT) { /* this is a member name, don't normalize */ TOKEN_SET(&val, string, cli_strdup(text)); val.type = TOK_UNNORM_IDENTIFIER; } else { switch(current->fsm_state) { case WaitParameterList: state->syntax_errors++; /* fall through */ case Base: case InsideInitializer: TOKEN_SET(&val, cstring, scope_use(current, text, leng)); break; case InsideVar: case InsideFunctionDecl: TOKEN_SET(&val, cstring, scope_declare(current, text, leng, state)); current->fsm_state = InsideInitializer; current->brackets = 0; break; case WaitFunctionName: TOKEN_SET(&val, cstring, scope_declare(current, text, leng, state)); current->fsm_state = WaitParameterList; break; } } break; case TOK_PAR_OPEN: switch(current->fsm_state) { case WaitFunctionName: /* fallthrough */ case WaitParameterList: current->fsm_state = InsideFunctionDecl; break; default: /* noop */ break; } break; case TOK_PAR_CLOSE: switch(current->fsm_state) { case WaitFunctionName: state->syntax_errors++; break; case WaitParameterList: current->fsm_state = Base; break; default: /* noop */ break; } break; case TOK_CURLY_BRACE_OPEN: switch(current->fsm_state) { case WaitFunctionName: /* fallthrough */ case WaitParameterList: case InsideFunctionDecl: /* in a syntactically correct * file, we would already be in * the Base state when we see a { */ current->fsm_state = Base; /* fall-through */ case InsideVar: case InsideInitializer: state->syntax_errors++; /* fall-through */ case Base: default: current->blocks++; break; } break; case TOK_CURLY_BRACE_CLOSE: if(current->blocks > 0) current->blocks--; else state->syntax_errors++; if(!current->blocks) { if(current->parent) { /* add dummy FUNCTION token to * mark function end */ TOKEN_SET(&val, cstring, "}"); add_token(state, &val); TOKEN_SET(&val, scope, NULL); val.type = TOK_FUNCTION; state->current = current = current->parent; } else{ /* extra } */ state->syntax_errors++; } } break; case TOK_BRACKET_OPEN: current->brackets++; break; case TOK_BRACKET_CLOSE: if(current->brackets > 0) current->brackets--; else state->syntax_errors++; break; case TOK_COMMA: if (current->fsm_state == InsideInitializer && current->brackets == 0 && current->blocks == 0) { /* initializer ended only if we * encountered a comma, and [] are * balanced. * This avoids switching state on: * var x = [4,y,u];*/ current->fsm_state = InsideVar; } break; case TOK_SEMICOLON: if (current->brackets == 0 && current->blocks == 0) { /* avoid switching state on unbalanced []: * var x = [test;testi]; */ current->fsm_state = Base; } break; case TOK_FUNCTION: current = scope_new(state); current->fsm_state = WaitFunctionName; TOKEN_SET(&val, scope, state->current); break; case TOK_StringLiteral: if(state->tokens.cnt > 1 && state->tokens.data[state->tokens.cnt-1].type == TOK_PLUS) { /* see if can fold */ yystype *prev_string = &state->tokens.data[state->tokens.cnt-2]; if(prev_string->type == TOK_StringLiteral) { char *str = TOKEN_GET(prev_string, string); size_t str_len = strlen(str); text = yyget_text(state->scanner); leng = yyget_leng(state->scanner); /* delete TOK_PLUS */ free_token(&state->tokens.data[--state->tokens.cnt]); str = cli_realloc(str, str_len + leng + 1); if (!str) break; strncpy(str+str_len, text, leng); str[str_len + leng] = '\0'; TOKEN_SET(prev_string, string, str); free(val.val.string); memset(&val, 0, sizeof(val)); val.vtype = vtype_undefined; continue; } } break; } if(val.vtype == vtype_undefined) { text = yyget_text(state->scanner); TOKEN_SET(&val, string, cli_strdup(text)); abort(); } add_token(state, &val); current->last_token = yv; memset(&val, 0, sizeof(val)); val.vtype = vtype_undefined; } }
vba_project_t * cli_vba_readdir(const char *dir, struct uniq *U, uint32_t which) { unsigned char *buf; const unsigned char vba56_signature[] = { 0xcc, 0x61 }; uint16_t record_count, buflen, ffff, byte_count; uint32_t offset; int i, j, fd, big_endian = FALSE; vba_project_t *vba_project; struct vba56_header v56h; off_t seekback; char fullname[1024], *hash; cli_dbgmsg("in cli_vba_readdir()\n"); if(dir == NULL) return NULL; /* * _VBA_PROJECT files are embedded within office documents (OLE2) */ if (!uniq_get(U, "_vba_project", 12, &hash)) return NULL; snprintf(fullname, sizeof(fullname), "%s"PATHSEP"%s_%u", dir, hash, which); fullname[sizeof(fullname)-1] = '\0'; fd = open(fullname, O_RDONLY|O_BINARY); if(fd == -1) return NULL; if(cli_readn(fd, &v56h, sizeof(struct vba56_header)) != sizeof(struct vba56_header)) { close(fd); return NULL; } if (memcmp(v56h.magic, vba56_signature, sizeof(v56h.magic)) != 0) { close(fd); return NULL; } i = vba_read_project_strings(fd, TRUE); if ((seekback = lseek(fd, 0, SEEK_CUR)) == -1) { cli_dbgmsg("vba_readdir: lseek() failed. Unable to guess VBA type\n"); close(fd); return NULL; } if (lseek(fd, sizeof(struct vba56_header), SEEK_SET) == -1) { cli_dbgmsg("vba_readdir: lseek() failed. Unable to guess VBA type\n"); close(fd); return NULL; } j = vba_read_project_strings(fd, FALSE); if(!i && !j) { close(fd); cli_dbgmsg("vba_readdir: Unable to guess VBA type\n"); return NULL; } if (i > j) { big_endian = TRUE; if (lseek(fd, seekback, SEEK_SET) == -1) { cli_dbgmsg("vba_readdir: call to lseek() while guessing big-endian has failed\n"); close(fd); return NULL; } cli_dbgmsg("vba_readdir: Guessing big-endian\n"); } else { cli_dbgmsg("vba_readdir: Guessing little-endian\n"); } /* junk some more stuff */ do if (cli_readn(fd, &ffff, 2) != 2) { close(fd); return NULL; } while(ffff != 0xFFFF); /* check for alignment error */ if(!seekandread(fd, -3, SEEK_CUR, &ffff, sizeof(uint16_t))) { close(fd); return NULL; } if (ffff != 0xFFFF) { if (lseek(fd, 1, SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() while checking alignment error has failed\n"); close(fd); return NULL; } } if(!read_uint16(fd, &ffff, big_endian)) { close(fd); return NULL; } if(ffff != 0xFFFF) { if (lseek(fd, ffff, SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() while checking alignment error has failed\n"); close(fd); return NULL; } } if(!read_uint16(fd, &ffff, big_endian)) { close(fd); return NULL; } if(ffff == 0xFFFF) ffff = 0; if (lseek(fd, ffff + 100, SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() failed\n"); close(fd); return NULL; } if(!read_uint16(fd, &record_count, big_endian)) { close(fd); return NULL; } cli_dbgmsg("vba_readdir: VBA Record count %d\n", record_count); if (record_count == 0) { /* No macros, assume clean */ close(fd); return NULL; } if (record_count > MAX_VBA_COUNT) { /* Almost certainly an error */ cli_dbgmsg("vba_readdir: VBA Record count too big\n"); close(fd); return NULL; } vba_project = create_vba_project(record_count, dir, U); if(vba_project == NULL) { close(fd); return NULL; } buf = NULL; buflen = 0; for(i = 0; i < record_count; i++) { uint16_t length; char *ptr; vba_project->colls[i] = 0; if(!read_uint16(fd, &length, big_endian)) break; if (length == 0) { cli_dbgmsg("vba_readdir: zero name length\n"); break; } if(length > buflen) { unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length); if(newbuf == NULL) break; buflen = length; buf = newbuf; } if (cli_readn(fd, buf, length) != length) { cli_dbgmsg("vba_readdir: read name failed\n"); break; } ptr = get_unicode_name((const char *)buf, length, big_endian); if(ptr == NULL) break; if (!(vba_project->colls[i]=uniq_get(U, ptr, strlen(ptr), &hash))) { cli_dbgmsg("vba_readdir: cannot find project %s (%s)\n", ptr, hash); free(ptr); break; } cli_dbgmsg("vba_readdir: project name: %s (%s)\n", ptr, hash); free(ptr); vba_project->name[i] = hash; if(!read_uint16(fd, &length, big_endian)) break; lseek(fd, length, SEEK_CUR); if(!read_uint16(fd, &ffff, big_endian)) break; if (ffff == 0xFFFF) { lseek(fd, 2, SEEK_CUR); if(!read_uint16(fd, &ffff, big_endian)) break; lseek(fd, ffff + 8, SEEK_CUR); } else lseek(fd, ffff + 10, SEEK_CUR); if(!read_uint16(fd, &byte_count, big_endian)) break; lseek(fd, (8 * byte_count) + 5, SEEK_CUR); if(!read_uint32(fd, &offset, big_endian)) break; cli_dbgmsg("vba_readdir: offset: %u\n", (unsigned int)offset); vba_project->offset[i] = offset; lseek(fd, 2, SEEK_CUR); } if(buf) free(buf); close(fd); if(i < record_count) { free(vba_project->name); free(vba_project->colls); free(vba_project->dir); free(vba_project->offset); free(vba_project); return NULL; } return vba_project; }
/* return count of valid strings found, 0 on error */ static int vba_read_project_strings(int fd, int big_endian) { unsigned char *buf = NULL; uint16_t buflen = 0; uint16_t length = 0; int ret = 0, getnewlength = 1; for(;;) { off_t offset; char *name; /* if no initial name length, exit */ if(getnewlength && !read_uint16(fd, &length, big_endian)) { ret = 0; break; } getnewlength = 0; /* if too short, break */ if (length < 6) { if (lseek(fd, -2, SEEK_CUR) == -1) { cli_dbgmsg("vba_read_project_strings: call to lseek() has failed\n"); ret = 0; } break; } /* ensure buffer is large enough */ if(length > buflen) { unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length); if(newbuf == NULL) { ret = 0; break; } buflen = length; buf = newbuf; } /* save current offset */ offset = lseek(fd, 0, SEEK_CUR); if (offset == -1) { cli_dbgmsg("vba_read_project_strings: call to lseek() has failed\n"); ret = 0; break; } /* if read name failed, break */ if(cli_readn(fd, buf, length) != (int)length) { cli_dbgmsg("read name failed - rewinding\n"); if (lseek(fd, offset, SEEK_SET) == -1) { cli_dbgmsg("call to lseek() in read name failed\n"); ret = 0; } break; } name = get_unicode_name((const char *)buf, length, big_endian); cli_dbgmsg("length: %d, name: %s\n", length, (name) ? name : "[null]"); /* if invalid name, break */ if((name == NULL) || (memcmp("*\\", name, 2) != 0) || (strchr("ghcd", name[2]) == NULL)) { /* Not a valid string, rewind */ if (lseek(fd, -(length+2), SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() after get_unicode_name has failed\n"); ret = 0; } free(name); break; } free(name); /* can't get length, break */ if(!read_uint16(fd, &length, big_endian)) { break; } ret++; /* continue on reasonable length value */ if ((length != 0) && (length != 65535)) { continue; } /* determine offset and run middle test */ offset = lseek(fd, 10, SEEK_CUR); if (offset == -1) { cli_dbgmsg("call to lseek() has failed\n"); ret = 0; break; } cli_dbgmsg("offset: %lu\n", (unsigned long)offset); vba56_test_middle(fd); getnewlength = 1; } free(buf); return ret; }
static int vba_read_project_strings(int fd, int big_endian) { unsigned char *buf = NULL; uint16_t buflen = 0; int ret = 0; for(;;) { off_t offset; uint16_t length; char *name; if(!read_uint16(fd, &length, big_endian)) break; if (length < 6) { lseek(fd, -2, SEEK_CUR); break; } if(length > buflen) { unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length); if(newbuf == NULL) { if(buf) free(buf); return 0; } buflen = length; buf = newbuf; } offset = lseek(fd, 0, SEEK_CUR); if(cli_readn(fd, buf, length) != (int)length) { cli_dbgmsg("read name failed - rewinding\n"); lseek(fd, offset, SEEK_SET); break; } name = get_unicode_name((const char *)buf, length, big_endian); cli_dbgmsg("length: %d, name: %s\n", length, (name) ? name : "[null]"); if((name == NULL) || (memcmp("*\\", name, 2) != 0) || (strchr("ghcd", name[2]) == NULL)) { /* Not a string */ lseek(fd, -(length+2), SEEK_CUR); if(name) free(name); break; } free(name); if(!read_uint16(fd, &length, big_endian)) { if(buf) free(buf); break; } ret++; if ((length != 0) && (length != 65535)) { lseek(fd, -2, SEEK_CUR); continue; } offset = lseek(fd, 10, SEEK_CUR); cli_dbgmsg("offset: %lu\n", (unsigned long)offset); vba56_test_middle(fd); } if(buf) free(buf); return ret; }
int cli_binhex(const char *dir, int desc) { #ifndef HAVE_MMAP cli_warnmsg("File not decoded - binhex decoding needs mmap() (for now)\n"); return CL_CLEAN; #else struct stat statb; char *buf, *start, *line; size_t size; long bytesleft; message *m; fileblob *fb; if(fstat(desc, &statb) < 0) return CL_EOPEN; size = (size_t)statb.st_size; if(size == 0) return CL_CLEAN; m = messageCreate(); if(m == NULL) return CL_EMEM; start = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0); if(buf == MAP_FAILED) { messageDestroy(m); return CL_EMEM; } cli_dbgmsg("mmap'ed binhex file\n"); bytesleft = (long)size; line = NULL; while(bytesleft > 0) { int length = 0; char *ptr, *newline; /*printf("%d: ", bytesleft);*/ for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) { length++; --bytesleft; } /*printf("%d: ", length);*/ newline = cli_realloc(line, (size_t)(length + 1)); if(newline == NULL) break; line = newline; memcpy(line, buf, length); line[length] = '\0'; /*puts(line);*/ if(messageAddStr(m, line) < 0) break; if((bytesleft > 0) && (*ptr == '\r')) { ptr++; bytesleft--; } buf = ++ptr; bytesleft--; } munmap(start, size); if(line) free(line); if(binhexBegin(m) == NULL) { messageDestroy(m); cli_errmsg("No binhex line found\n"); return CL_EFORMAT; } /* similar to binhexMessage */ messageSetEncoding(m, "x-binhex"); fb = messageToFileblob(m, dir, 1); if(fb) { cli_dbgmsg("Binhex file decoded to %s\n", fileblobGetFilename(fb)); fileblobDestroy(fb); } else cli_errmsg("Couldn't decode binhex file to %s\n", dir); messageDestroy(m); if(fb) return CL_CLEAN; /* a lie - but it gets things going */ return CL_EIO; /* probably CL_EMEM, but we can't tell at this layer */ #endif }
/* * Returns <0 for failure */ int blobAddData(blob *b, const unsigned char *data, size_t len) { #if HAVE_CLI_GETPAGESIZE static int pagesize; int growth; #endif assert(b != NULL); assert(b->magic == BLOBCLASS); assert(data != NULL); if(len == 0) return 0; if(b->isClosed) { /* * Should be cli_dbgmsg, but I want to see them for now, * and cli_dbgmsg doesn't support debug levels */ cli_warnmsg("Reopening closed blob\n"); b->isClosed = 0; } /* * The payoff here is between reducing the number of calls to * malloc/realloc and not overallocating memory. A lot of machines * are more tight with memory than one may imagine which is why * we don't just allocate a *huge* amount and be done with it. Closing * the blob helps because that reclaims memory. If you know the maximum * size of a blob before you start adding data, use blobGrow() that's * the most optimum */ #if HAVE_CLI_GETPAGESIZE if(pagesize == 0) { pagesize = cli_getpagesize(); if(pagesize == 0) pagesize = 4096; } growth = pagesize; if(len >= (size_t)pagesize) growth = ((len / pagesize) + 1) * pagesize; /*cli_dbgmsg("blobGrow: b->size %lu, b->len %lu, len %lu, growth = %u\n", b->size, b->len, len, growth);*/ if(b->data == NULL) { assert(b->len == 0); assert(b->size == 0); b->size = growth; b->data = cli_malloc(growth); } else if(b->size < b->len + (off_t)len) { unsigned char *p = cli_realloc(b->data, b->size + growth); if(p == NULL) return -1; b->size += growth; b->data = p; } #else if(b->data == NULL) { assert(b->len == 0); assert(b->size == 0); b->size = (off_t)len * 4; b->data = cli_malloc(b->size); } else if(b->size < b->len + (off_t)len) { unsigned char *p = cli_realloc(b->data, b->size + (len * 4)); if(p == NULL) return -1; b->size += (off_t)len * 4; b->data = p; } #endif if(b->data) { memcpy(&b->data[b->len], data, len); b->len += (off_t)len; } return 0; }