From 76ecf81428c161a98a5621b55a64cb8515f80585 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Jul 2005 01:10:09 +0000 Subject: [PATCH] r8273: fixed some memory leaks in smbscript. This required converting file_load() to use talloc, which impacted quite a few bits of code, including our smb.conf processing. took the opportunity to remove the gloabls in params.c while doing this (This used to be commit b220756cb4f1d201ba3e771ca67e4bfae5eae748) --- source4/intl/lang_tdb.c | 11 ++- source4/lib/util_file.c | 33 +++----- source4/param/params.c | 112 ++++++++++++--------------- source4/scripting/ejs/ejsrpc.c | 21 ----- source4/scripting/ejs/ejsrpc.h | 2 - source4/scripting/ejs/smbcalls_rpc.c | 19 +++-- source4/scripting/ejs/smbscript.c | 3 +- source4/torture/gentest.c | 4 +- source4/torture/torture.c | 2 +- source4/utils/ndrdump.c | 4 +- 10 files changed, 90 insertions(+), 121 deletions(-) diff --git a/source4/intl/lang_tdb.c b/source4/intl/lang_tdb.c index de08c82ce4e..be8bce2391d 100644 --- a/source4/intl/lang_tdb.c +++ b/source4/intl/lang_tdb.c @@ -37,14 +37,19 @@ static BOOL load_msg(const char *msg_file) int num_lines, i; char *msgid, *msgstr; TDB_DATA key, data; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); - lines = file_lines_load(msg_file, &num_lines); + lines = file_lines_load(msg_file, &num_lines, tmp_ctx); if (!lines) { + talloc_free(tmp_ctx); return False; } - if (tdb_lockall(tdb) != 0) return False; + if (tdb_lockall(tdb) != 0) { + talloc_free(tmp_ctx); + return False; + } /* wipe the db */ tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); @@ -71,7 +76,7 @@ static BOOL load_msg(const char *msg_file) } } - file_lines_free(lines); + talloc_free(tmp_ctx); tdb_unlockall(tdb); return True; diff --git a/source4/lib/util_file.c b/source4/lib/util_file.c index e02198754d5..a7d29d1a1dc 100644 --- a/source4/lib/util_file.c +++ b/source4/lib/util_file.c @@ -190,18 +190,18 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f) load a file into memory from a fd. ****************************************************************************/ -char *fd_load(int fd, size_t *size) +char *fd_load(int fd, size_t *size, TALLOC_CTX *mem_ctx) { struct stat sbuf; char *p; if (fstat(fd, &sbuf) != 0) return NULL; - p = (char *)malloc(sbuf.st_size+1); + p = (char *)talloc_size(mem_ctx, sbuf.st_size+1); if (!p) return NULL; if (read(fd, p, sbuf.st_size) != sbuf.st_size) { - SAFE_FREE(p); + talloc_free(p); return NULL; } p[sbuf.st_size] = 0; @@ -214,7 +214,7 @@ char *fd_load(int fd, size_t *size) /**************************************************************************** load a file into memory ****************************************************************************/ -char *file_load(const char *fname, size_t *size) +char *file_load(const char *fname, size_t *size, TALLOC_CTX *mem_ctx) { int fd; char *p; @@ -224,7 +224,7 @@ char *file_load(const char *fname, size_t *size) fd = open(fname,O_RDONLY); if (fd == -1) return NULL; - p = fd_load(fd, size); + p = fd_load(fd, size, mem_ctx); close(fd); @@ -254,12 +254,12 @@ void *map_file(char *fname, size_t size) } #endif if (!p) { - p = file_load(fname, &s2); + p = file_load(fname, &s2, talloc_autofree_context()); if (!p) return NULL; if (s2 != size) { DEBUG(1,("incorrect size for %s - got %d expected %d\n", fname, s2, size)); - if (p) free(p); + talloc_free(p); return NULL; } } @@ -308,12 +308,12 @@ static char **file_lines_parse(char *p, size_t size, int *numlines) load a file into memory and return an array of pointers to lines in the file must be freed with file_lines_free(). ****************************************************************************/ -char **file_lines_load(const char *fname, int *numlines) +char **file_lines_load(const char *fname, int *numlines, TALLOC_CTX *mem_ctx) { char *p; size_t size; - p = file_load(fname, &size); + p = file_load(fname, &size, mem_ctx); if (!p) return NULL; return file_lines_parse(p, size, numlines); @@ -324,29 +324,18 @@ load a fd into memory and return an array of pointers to lines in the file must be freed with file_lines_free(). If convert is true calls unix_to_dos on the list. ****************************************************************************/ -char **fd_lines_load(int fd, int *numlines) +char **fd_lines_load(int fd, int *numlines, TALLOC_CTX *mem_ctx) { char *p; size_t size; - p = fd_load(fd, &size); + p = fd_load(fd, &size, mem_ctx); if (!p) return NULL; return file_lines_parse(p, size, numlines); } -/**************************************************************************** -free lines loaded with file_lines_load -****************************************************************************/ -void file_lines_free(char **lines) -{ - if (!lines) return; - SAFE_FREE(lines[0]); - SAFE_FREE(lines); -} - - /**************************************************************************** take a lislist of lines and modify them to produce a list where \ continues a line diff --git a/source4/param/params.c b/source4/param/params.c index 34d537c395a..d59e11a895f 100644 --- a/source4/param/params.c +++ b/source4/param/params.c @@ -89,25 +89,14 @@ #define BUFR_INC 1024 -/* -------------------------------------------------------------------------- ** - * Variables... - * - * DEBUGLEVEL - The ubiquitous DEBUGLEVEL. This determines which DEBUG() - * messages will be produced. - * bufr - pointer to a global buffer. This is probably a kludge, - * but it was the nicest kludge I could think of (for now). - * bSize - The size of the global buffer . - */ - -static char *bufr = NULL; -static int bSize = 0; - /* we can't use FILE* due to the 256 fd limit - use this cheap hack instead */ typedef struct { char *buf; char *p; size_t size; + char *bufr; + int bSize; } myFILE; static int mygetc(myFILE *f) @@ -119,9 +108,7 @@ static int mygetc(myFILE *f) static void myfile_close(myFILE *f) { - if (!f) return; - SAFE_FREE(f->buf); - SAFE_FREE(f); + talloc_free(f); } /* -------------------------------------------------------------------------- ** @@ -235,58 +222,58 @@ static BOOL Section( myFILE *InFile, BOOL (*sfunc)(const char *) ) { /* Check that the buffer is big enough for the next character. */ - if( i > (bSize - 2) ) + if( i > (InFile->bSize - 2) ) { char *tb; - tb = realloc_p(bufr, char, bSize + BUFR_INC); + tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC); if( NULL == tb ) { DEBUG(0, ("%s Memory re-allocation failure.", func) ); return( False ); } - bufr = tb; - bSize += BUFR_INC; + InFile->bufr = tb; + InFile->bSize += BUFR_INC; } /* Handle a single character. */ switch( c ) { case ']': /* Found the closing bracket. */ - bufr[end] = '\0'; + InFile->bufr[end] = '\0'; if( 0 == end ) /* Don't allow an empty name. */ { DEBUG(0, ("%s Empty section name in configuration file.\n", func )); return( False ); } - if( !sfunc(bufr) ) /* Got a valid name. Deal with it. */ + if( !sfunc(InFile->bufr) ) /* Got a valid name. Deal with it. */ return( False ); (void)EatComment( InFile ); /* Finish off the line. */ return( True ); case '\n': /* Got newline before closing ']'. */ - i = Continuation( bufr, i ); /* Check for line continuation. */ + i = Continuation( InFile->bufr, i ); /* Check for line continuation. */ if( i < 0 ) { - bufr[end] = '\0'; + InFile->bufr[end] = '\0'; DEBUG(0, ("%s Badly formed line in configuration file: %s\n", - func, bufr )); + func, InFile->bufr )); return( False ); } - end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i); + end = ( (i > 0) && (' ' == InFile->bufr[i - 1]) ) ? (i - 1) : (i); c = mygetc( InFile ); /* Continue with next line. */ break; default: /* All else are a valid name chars. */ if( isspace( c ) ) /* One space per whitespace region. */ { - bufr[end] = ' '; + InFile->bufr[end] = ' '; i = end + 1; c = EatWhitespace( InFile ); } else /* All others copy verbatim. */ { - bufr[i++] = c; + InFile->bufr[i++] = c; end = i; c = mygetc( InFile ); } @@ -294,7 +281,7 @@ static BOOL Section( myFILE *InFile, BOOL (*sfunc)(const char *) ) } /* We arrive here if we've met the EOF before the closing bracket. */ - DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, bufr )); + DEBUG(0, ("%s Unexpected EOF in the configuration file\n", func)); return( False ); } /* Section */ @@ -332,18 +319,18 @@ static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *) while( 0 == vstart ) /* Loop until we've found the start of the value. */ { - if( i > (bSize - 2) ) /* Ensure there's space for next char. */ + if( i > (InFile->bSize - 2) ) /* Ensure there's space for next char. */ { char *tb; - tb = realloc_p( bufr, char, bSize + BUFR_INC ); + tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC ); if( NULL == tb ) { DEBUG(0, ("%s Memory re-allocation failure.", func) ); return( False ); } - bufr = tb; - bSize += BUFR_INC; + InFile->bufr = tb; + InFile->bSize += BUFR_INC; } switch( c ) @@ -354,41 +341,41 @@ static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *) DEBUG(0, ("%s Invalid parameter name in config. file.\n", func )); return( False ); } - bufr[end++] = '\0'; /* Mark end of string & advance. */ + InFile->bufr[end++] = '\0'; /* Mark end of string & advance. */ i = end; /* New string starts here. */ vstart = end; /* New string is parameter value. */ - bufr[i] = '\0'; /* New string is nul, for now. */ + InFile->bufr[i] = '\0'; /* New string is nul, for now. */ break; case '\n': /* Find continuation char, else error. */ - i = Continuation( bufr, i ); + i = Continuation( InFile->bufr, i ); if( i < 0 ) { - bufr[end] = '\0'; + InFile->bufr[end] = '\0'; DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n", - func, bufr )); + func, InFile->bufr )); return( True ); } - end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i); + end = ( (i > 0) && (' ' == InFile->bufr[i - 1]) ) ? (i - 1) : (i); c = mygetc( InFile ); /* Read past eoln. */ break; case '\0': /* Shouldn't have EOF within param name. */ case EOF: - bufr[i] = '\0'; - DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, bufr )); + InFile->bufr[i] = '\0'; + DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, InFile->bufr )); return( True ); default: if( isspace( c ) ) /* One ' ' per whitespace region. */ { - bufr[end] = ' '; + InFile->bufr[end] = ' '; i = end + 1; c = EatWhitespace( InFile ); } else /* All others verbatim. */ { - bufr[i++] = c; + InFile->bufr[i++] = c; end = i; c = mygetc( InFile ); } @@ -400,18 +387,18 @@ static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *) while( (EOF !=c) && (c > 0) ) { - if( i > (bSize - 2) ) /* Make sure there's enough room. */ + if( i > (InFile->bSize - 2) ) /* Make sure there's enough room. */ { char *tb; - tb = realloc_p( bufr, char, bSize + BUFR_INC ); + tb = talloc_realloc(InFile, InFile->bufr, char, InFile->bSize + BUFR_INC ); if( NULL == tb ) { DEBUG(0, ("%s Memory re-allocation failure.", func) ); return( False ); } - bufr = tb; - bSize += BUFR_INC; + InFile->bufr = tb; + InFile->bSize += BUFR_INC; } switch( c ) @@ -421,28 +408,28 @@ static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *) break; /* removes them. */ case '\n': /* Marks end of value unless there's a '\'. */ - i = Continuation( bufr, i ); + i = Continuation( InFile->bufr, i ); if( i < 0 ) c = 0; else { - for( end = i; (end >= 0) && isspace((int)bufr[end]); end-- ) + for( end = i; (end >= 0) && isspace((int)InFile->bufr[end]); end-- ) ; c = mygetc( InFile ); } break; default: /* All others verbatim. Note that spaces do */ - bufr[i++] = c; /* not advance . This allows trimming */ + InFile->bufr[i++] = c; /* not advance . This allows trimming */ if( !isspace( c ) ) /* of whitespace at the end of the line. */ end = i; c = mygetc( InFile ); break; } } - bufr[end] = '\0'; /* End of value. */ + InFile->bufr[end] = '\0'; /* End of value. */ - return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */ + return( pfunc( InFile->bufr, &InFile->bufr[vstart] ) ); /* Pass name & value to pfunc(). */ } /* Parameter */ static BOOL Parse( myFILE *InFile, @@ -520,20 +507,22 @@ static myFILE *OpenConfFile( const char *FileName ) const char *func = "params.c:OpenConfFile() -"; myFILE *ret; - ret = malloc_p(myFILE); + ret = talloc(talloc_autofree_context(), myFILE); if (!ret) return NULL; - ret->buf = file_load(FileName, &ret->size); + ret->buf = file_load(FileName, &ret->size, ret); if( NULL == ret->buf ) { DEBUG( 1, ("%s Unable to open configuration file \"%s\":\n\t%s\n", func, FileName, strerror(errno)) ); - SAFE_FREE(ret); + talloc_free(ret); return NULL; } ret->p = ret->buf; + ret->bufr = NULL; + ret->bSize = 0; return( ret ); } /* OpenConfFile */ @@ -564,24 +553,23 @@ BOOL pm_process( const char *FileName, DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) ); - if( NULL != bufr ) /* If we already have a buffer */ + if( NULL != InFile->bufr ) /* If we already have a buffer */ result = Parse( InFile, sfunc, pfunc ); /* (recursive call), then just */ /* use it. */ else /* If we don't have a buffer */ { /* allocate one, then parse, */ - bSize = BUFR_INC; /* then free. */ - bufr = (char *)malloc( bSize ); - if( NULL == bufr ) + InFile->bSize = BUFR_INC; /* then free. */ + InFile->bufr = talloc_array(InFile, char, InFile->bSize ); + if( NULL == InFile->bufr ) { DEBUG(0,("%s memory allocation failure.\n", func)); myfile_close(InFile); return( False ); } result = Parse( InFile, sfunc, pfunc ); - SAFE_FREE( bufr ); - bufr = NULL; - bSize = 0; + InFile->bufr = NULL; + InFile->bSize = 0; } myfile_close(InFile); diff --git a/source4/scripting/ejs/ejsrpc.c b/source4/scripting/ejs/ejsrpc.c index cd7e0c92116..f2c2b258e43 100644 --- a/source4/scripting/ejs/ejsrpc.c +++ b/source4/scripting/ejs/ejsrpc.c @@ -26,27 +26,6 @@ #include "librpc/gen_ndr/ndr_lsa.h" #include "scripting/ejs/ejsrpc.h" -NTSTATUS ejs_pull_rpc(int eid, const char *callname, - struct MprVar *v, void *ptr, ejs_pull_function_t ejs_pull) -{ - struct ejs_rpc *ejs = talloc(ptr, struct ejs_rpc); - NT_STATUS_HAVE_NO_MEMORY(ejs); - ejs->eid = eid; - ejs->callname = callname; - return ejs_pull(ejs, v, ptr); -} - - -NTSTATUS ejs_push_rpc(int eid, const char *callname, - struct MprVar *v, const void *ptr, ejs_push_function_t ejs_push) -{ - struct ejs_rpc *ejs = talloc(ptr, struct ejs_rpc); - NT_STATUS_HAVE_NO_MEMORY(ejs); - ejs->eid = eid; - ejs->callname = callname; - return ejs_push(ejs, v, ptr); -} - /* set the switch var to be used by the next union switch */ diff --git a/source4/scripting/ejs/ejsrpc.h b/source4/scripting/ejs/ejsrpc.h index 6914988bc87..e410535b6cc 100644 --- a/source4/scripting/ejs/ejsrpc.h +++ b/source4/scripting/ejs/ejsrpc.h @@ -46,8 +46,6 @@ NTSTATUS smbcalls_register_ejs(const char *name, int ejs_rpc_call(int eid, int argc, struct MprVar **argv, const char *callname, ejs_pull_function_t ejs_pull, ejs_push_function_t ejs_push); -NTSTATUS ejs_pull_rpc(int eid, const char *callname, struct MprVar *v, void *ptr, ejs_pull_function_t ejs_pull); -NTSTATUS ejs_push_rpc(int eid, const char *callname, struct MprVar *v, const void *ptr, ejs_push_function_t ejs_push); NTSTATUS ejs_pull_struct_start(struct ejs_rpc *ejs, struct MprVar **v, const char *name); NTSTATUS ejs_push_struct_start(struct ejs_rpc *ejs, struct MprVar **v, const char *name); diff --git a/source4/scripting/ejs/smbcalls_rpc.c b/source4/scripting/ejs/smbcalls_rpc.c index 12b0d95e8e5..8a5389fbaba 100644 --- a/source4/scripting/ejs/smbcalls_rpc.c +++ b/source4/scripting/ejs/smbcalls_rpc.c @@ -105,6 +105,7 @@ done: void *ptr; struct rpc_request *req; int callnum; + struct ejs_rpc *ejs; if (argc != 2 || argv[0]->type != MPR_TYPE_OBJECT || @@ -132,15 +133,24 @@ done: } callnum = call - iface->calls; + ejs = talloc(mprMemCtx(), struct ejs_rpc); + if (ejs == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + ejs->eid = eid; + ejs->callname = callname; + /* allocate the C structure */ - ptr = talloc_zero_size(mprMemCtx(), call->struct_size); + ptr = talloc_zero_size(ejs, call->struct_size); if (ptr == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } /* convert the mpr object into a C structure */ - status = ejs_pull_rpc(eid, callname, io, ptr, ejs_pull); + status = ejs_pull(ejs, io, ptr); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -154,7 +164,6 @@ done: req = dcerpc_ndr_request_send(p, NULL, iface, callnum, ptr, ptr); if (req == NULL) { status = NT_STATUS_NO_MEMORY; - talloc_free(ptr); goto done; } status = dcerpc_ndr_request_recv(req); @@ -164,10 +173,10 @@ done: ndr_print_function_debug(call->ndr_print, call->name, NDR_OUT, ptr); } - status = ejs_push_rpc(eid, callname, io, ptr, ejs_push); + status = ejs_push(ejs, io, ptr); - talloc_free(ptr); done: + talloc_free(ejs); ejsSetReturnValue(eid, mprNTSTATUS(status)); if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) { return -1; diff --git a/source4/scripting/ejs/smbscript.c b/source4/scripting/ejs/smbscript.c index 244ae0b42aa..f7556b53840 100644 --- a/source4/scripting/ejs/smbscript.c +++ b/source4/scripting/ejs/smbscript.c @@ -94,12 +94,13 @@ void ejs_exception(const char *reason) for (i=1;argv[i];i++) { argv_list = str_list_add(argv_list, argv[i]); } + talloc_steal(mem_ctx, argv_list); v = mprList("ARGV", argv_list); mprSetPropertyValue(&v, "length", mprCreateIntegerVar(i-1)); mprCreateProperty(ejsGetGlobalObject(eid), "ARGV", &v); /* load the script and advance past interpreter line*/ - script = file_load(fname, &script_size); + script = file_load(fname, &script_size, mem_ctx); if ((script_size > 2) && script[0] == '#' && script[1] == '!') { script += 2; diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index d6f5046820f..6adcbbc0fe0 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -2037,7 +2037,7 @@ static BOOL start_gentest(void) /* generate the seeds - after this everything is deterministic */ if (options.use_preset_seeds) { int numops; - char **preset = file_lines_load(options.seeds_file, &numops); + char **preset = file_lines_load(options.seeds_file, &numops, NULL); if (!preset) { printf("Failed to load %s - %s\n", options.seeds_file, strerror(errno)); exit(1); @@ -2186,7 +2186,7 @@ static void usage(void) options.analyze_continuous = True; break; case 'i': - options.ignore_patterns = file_lines_load(optarg, NULL); + options.ignore_patterns = file_lines_load(optarg, NULL, NULL); break; case 'h': usage(); diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 6b993aa7abb..87aba2060ab 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -2068,7 +2068,7 @@ double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result p = lp_parm_string(-1, "torture", "unclist"); if (p) { - unc_list = file_lines_load(p, &num_unc_names); + unc_list = file_lines_load(p, &num_unc_names, NULL); if (!unc_list || num_unc_names <= 0) { printf("Failed to load unc names list from '%s'\n", p); exit(1); diff --git a/source4/utils/ndrdump.c b/source4/utils/ndrdump.c index 58cdeb13c3a..0cc96bfe122 100644 --- a/source4/utils/ndrdump.c +++ b/source4/utils/ndrdump.c @@ -188,7 +188,7 @@ static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size) exit(1); } - data = (uint8_t *)file_load(ctx_filename, &size); + data = (uint8_t *)file_load(ctx_filename, &size, mem_ctx); if (!data) { perror(ctx_filename); exit(1); @@ -213,7 +213,7 @@ static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size) } if (filename) - data = (uint8_t *)file_load(filename, &size); + data = (uint8_t *)file_load(filename, &size, mem_ctx); else data = (uint8_t *)stdin_load(mem_ctx, &size); -- 2.34.1