1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 09:12:24 +00:00

Another big batch of memory leak fixes, again mostly on error paths.

The most interesting one is printer_add_enum, which I've modified to
take a char ** rather than a char * so that it can both realloc its
input buffer _and_ return NULL to indicate error.

[originally from svn r9959]
This commit is contained in:
Simon Tatham 2013-07-22 07:11:54 +00:00
parent 4c61cb20a1
commit b99bec3b02
9 changed files with 107 additions and 42 deletions

View File

@ -448,6 +448,8 @@ char *staticwrap(struct ctlpos *cp, HWND hwnd, char *text, int *lines)
if (lines) *lines = nlines; if (lines) *lines = nlines;
sfree(pwidths);
return ret; return ret;
} }
@ -1665,6 +1667,8 @@ void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
winctrl_add_shortcuts(dp, c); winctrl_add_shortcuts(dp, c);
if (actual_base_id == base_id) if (actual_base_id == base_id)
base_id += num_ids; base_id += num_ids;
} else {
sfree(data);
} }
if (colstart >= 0) { if (colstart >= 0) {

View File

@ -2197,8 +2197,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
reconfig_result = reconfig_result =
do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0); do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0);
reconfiguring = FALSE; reconfiguring = FALSE;
if (!reconfig_result) if (!reconfig_result) {
conf_free(prev_conf);
break; break;
}
conf_cache_data(); conf_cache_data();
@ -4903,10 +4905,17 @@ void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_des
GlobalFree(clipdata2); GlobalFree(clipdata2);
return; return;
} }
if (!(lock = GlobalLock(clipdata))) if (!(lock = GlobalLock(clipdata))) {
GlobalFree(clipdata);
GlobalFree(clipdata2);
return; return;
if (!(lock2 = GlobalLock(clipdata2))) }
if (!(lock2 = GlobalLock(clipdata2))) {
GlobalUnlock(clipdata);
GlobalFree(clipdata);
GlobalFree(clipdata2);
return; return;
}
memcpy(lock, data, len * sizeof(wchar_t)); memcpy(lock, data, len * sizeof(wchar_t));
WideCharToMultiByte(CP_ACP, 0, data, len, lock2, len2, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, data, len, lock2, len2, NULL, NULL);

View File

@ -410,16 +410,20 @@ static IShellLink *make_shell_link(const char *appname,
/* Check if this is a valid session, otherwise don't add. */ /* Check if this is a valid session, otherwise don't add. */
if (sessionname) { if (sessionname) {
psettings_tmp = open_settings_r(sessionname); psettings_tmp = open_settings_r(sessionname);
if (!psettings_tmp) if (!psettings_tmp) {
sfree(app_path);
return NULL; return NULL;
}
close_settings_r(psettings_tmp); close_settings_r(psettings_tmp);
} }
/* Create the new item. */ /* Create the new item. */
if (!SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL, if (!SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, CLSCTX_INPROC_SERVER,
COMPTR(IShellLink, &ret)))) COMPTR(IShellLink, &ret)))) {
sfree(app_path);
return NULL; return NULL;
}
/* Set path, parameters, icon and description. */ /* Set path, parameters, icon and description. */
ret->lpVtbl->SetPath(ret, app_path); ret->lpVtbl->SetPath(ret, app_path);

View File

@ -420,11 +420,11 @@ static int save_ssh1_pubkey(char *filename, struct RSAKey *key)
char *dec1, *dec2; char *dec1, *dec2;
FILE *fp; FILE *fp;
dec1 = bignum_decimal(key->exponent);
dec2 = bignum_decimal(key->modulus);
fp = fopen(filename, "wb"); fp = fopen(filename, "wb");
if (!fp) if (!fp)
return 0; return 0;
dec1 = bignum_decimal(key->exponent);
dec2 = bignum_decimal(key->modulus);
fprintf(fp, "%d %s %s %s\n", fprintf(fp, "%d %s %s %s\n",
bignum_bitcount(key->modulus), dec1, dec2, key->comment); bignum_bitcount(key->modulus), dec1, dec2, key->comment);
fclose(fp); fclose(fp);
@ -1256,9 +1256,11 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
if (!state->generation_thread_exists) { if (!state->generation_thread_exists) {
char filename[FILENAME_MAX]; char filename[FILENAME_MAX];
if (prompt_keyfile(hwnd, "Load private key:", if (prompt_keyfile(hwnd, "Load private key:",
filename, 0, LOWORD(wParam)==IDC_LOAD)) filename, 0, LOWORD(wParam)==IDC_LOAD)) {
load_key_file(hwnd, state, filename_from_str(filename), Filename *fn = filename_from_str(filename);
LOWORD(wParam) != IDC_LOAD); load_key_file(hwnd, state, fn, LOWORD(wParam) != IDC_LOAD);
filename_free(fn);
}
} }
break; break;
} }

View File

@ -811,8 +811,10 @@ static void *get_keylist1(int *length)
retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL); retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
assert(retval == 1); assert(retval == 1);
response = vresponse; response = vresponse;
if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
sfree(response);
return NULL; return NULL;
}
ret = snewn(resplen-5, unsigned char); ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5); memcpy(ret, response+5, resplen-5);
@ -846,8 +848,10 @@ static void *get_keylist2(int *length)
retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL); retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
assert(retval == 1); assert(retval == 1);
response = vresponse; response = vresponse;
if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
sfree(response);
return NULL; return NULL;
}
ret = snewn(resplen-5, unsigned char); ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5); memcpy(ret, response+5, resplen-5);
@ -942,12 +946,17 @@ static void answer_msg(void *msg)
goto failure; goto failure;
p += i; p += i;
i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus); i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
if (i < 0) if (i < 0) {
freebn(reqkey.exponent);
goto failure; goto failure;
}
p += i; p += i;
i = ssh1_read_bignum(p, msgend - p, &challenge); i = ssh1_read_bignum(p, msgend - p, &challenge);
if (i < 0) if (i < 0) {
freebn(reqkey.exponent);
freebn(reqkey.modulus);
goto failure; goto failure;
}
p += i; p += i;
if (msgend < p+16) { if (msgend < p+16) {
freebn(reqkey.exponent); freebn(reqkey.exponent);
@ -1437,10 +1446,12 @@ static void prompt_add_keyfile(void)
of.lpstrTitle = "Select Private Key File"; of.lpstrTitle = "Select Private Key File";
of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER; of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
if (request_file(keypath, &of, TRUE, FALSE)) { if (request_file(keypath, &of, TRUE, FALSE)) {
if(strlen(filelist) > of.nFileOffset) if(strlen(filelist) > of.nFileOffset) {
/* Only one filename returned? */ /* Only one filename returned? */
add_keyfile(filename_from_str(filelist)); Filename *fn = filename_from_str(filelist);
else { add_keyfile(fn);
filename_free(fn);
} else {
/* we are returned a bunch of strings, end to /* we are returned a bunch of strings, end to
* end. first string is the directory, the * end. first string is the directory, the
* rest the filenames. terminated with an * rest the filenames. terminated with an
@ -1450,7 +1461,9 @@ static void prompt_add_keyfile(void)
char *filewalker = filelist + strlen(dir) + 1; char *filewalker = filelist + strlen(dir) + 1;
while (*filewalker != '\0') { while (*filewalker != '\0') {
char *filename = dupcat(dir, "\\", filewalker, NULL); char *filename = dupcat(dir, "\\", filewalker, NULL);
add_keyfile(filename_from_str(filename)); Filename *fn = filename_from_str(filename);
add_keyfile(fn);
filename_free(fn);
sfree(filename); sfree(filename);
filewalker += strlen(filewalker) + 1; filewalker += strlen(filewalker) + 1;
} }
@ -1908,6 +1921,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
#ifdef DEBUG_IPC #ifdef DEBUG_IPC
debug(("couldn't get user SID\n")); debug(("couldn't get user SID\n"));
#endif #endif
CloseHandle(filemap);
return 0; return 0;
} }
@ -1915,6 +1929,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
#ifdef DEBUG_IPC #ifdef DEBUG_IPC
debug(("couldn't get default SID\n")); debug(("couldn't get default SID\n"));
#endif #endif
CloseHandle(filemap);
sfree(ourself);
return 0; return 0;
} }
@ -1926,6 +1942,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
debug(("couldn't get owner info for filemap: %d\n", debug(("couldn't get owner info for filemap: %d\n",
rc)); rc));
#endif #endif
CloseHandle(filemap);
sfree(ourself);
sfree(ourself2);
return 0; return 0;
} }
#ifdef DEBUG_IPC #ifdef DEBUG_IPC
@ -1944,6 +1963,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
if (!EqualSid(mapowner, ourself) && if (!EqualSid(mapowner, ourself) &&
!EqualSid(mapowner, ourself2)) { !EqualSid(mapowner, ourself2)) {
CloseHandle(filemap); CloseHandle(filemap);
LocalFree(psd);
sfree(ourself);
sfree(ourself2);
return 0; /* security ID mismatch! */ return 0; /* security ID mismatch! */
} }
#ifdef DEBUG_IPC #ifdef DEBUG_IPC
@ -2127,7 +2149,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
command = ""; command = "";
break; break;
} else { } else {
add_keyfile(filename_from_str(argv[i])); Filename *fn = filename_from_str(argv[i]);
add_keyfile(fn);
filename_free(fn);
added_keys = TRUE; added_keys = TRUE;
} }
} }

View File

@ -209,8 +209,10 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, PAGE_READWRITE, filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, PAGE_READWRITE,
0, AGENT_MAX_MSGLEN, mapname); 0, AGENT_MAX_MSGLEN, mapname);
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
sfree(mapname);
return 1; /* *out == NULL, so failure */ return 1; /* *out == NULL, so failure */
}
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
memcpy(p, in, inlen); memcpy(p, in, inlen);
cds.dwData = AGENT_COPYDATA_ID; cds.dwData = AGENT_COPYDATA_ID;
@ -237,6 +239,7 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
data->hwnd = hwnd; data->hwnd = hwnd;
if (CreateThread(NULL, 0, agent_query_thread, data, 0, &threadid)) if (CreateThread(NULL, 0, agent_query_thread, data, 0, &threadid))
return 0; return 0;
sfree(mapname);
sfree(data); sfree(data);
} }
#endif #endif
@ -258,6 +261,7 @@ int agent_query(void *in, int inlen, void **out, int *outlen,
} }
UnmapViewOfFile(p); UnmapViewOfFile(p);
CloseHandle(filemap); CloseHandle(filemap);
sfree(mapname);
if (psd) if (psd)
LocalFree(psd); LocalFree(psd);
sfree(usersid); sfree(usersid);

View File

@ -18,39 +18,39 @@ struct printer_job_tag {
HANDLE hprinter; HANDLE hprinter;
}; };
static char *printer_add_enum(int param, DWORD level, char *buffer, static int printer_add_enum(int param, DWORD level, char **buffer,
int offset, int *nprinters_ptr) int offset, int *nprinters_ptr)
{ {
DWORD needed = 0, nprinters = 0; DWORD needed = 0, nprinters = 0;
buffer = sresize(buffer, offset+512, char); *buffer = sresize(*buffer, offset+512, char);
/* /*
* Exploratory call to EnumPrinters to determine how much space * Exploratory call to EnumPrinters to determine how much space
* we'll need for the output. Discard the return value since it * we'll need for the output. Discard the return value since it
* will almost certainly be a failure due to lack of space. * will almost certainly be a failure due to lack of space.
*/ */
EnumPrinters(param, NULL, level, buffer+offset, 512, EnumPrinters(param, NULL, level, (*buffer)+offset, 512,
&needed, &nprinters); &needed, &nprinters);
if (needed < 512) if (needed < 512)
needed = 512; needed = 512;
buffer = sresize(buffer, offset+needed, char); *buffer = sresize(*buffer, offset+needed, char);
if (EnumPrinters(param, NULL, level, buffer+offset, if (EnumPrinters(param, NULL, level, (*buffer)+offset,
needed, &needed, &nprinters) == 0) needed, &needed, &nprinters) == 0)
return NULL; return FALSE;
*nprinters_ptr += nprinters; *nprinters_ptr += nprinters;
return buffer; return TRUE;
} }
printer_enum *printer_start_enum(int *nprinters_ptr) printer_enum *printer_start_enum(int *nprinters_ptr)
{ {
printer_enum *ret = snew(printer_enum); printer_enum *ret = snew(printer_enum);
char *buffer = NULL, *retval; char *buffer = NULL;
*nprinters_ptr = 0; /* default return value */ *nprinters_ptr = 0; /* default return value */
buffer = snewn(512, char); buffer = snewn(512, char);
@ -71,12 +71,9 @@ printer_enum *printer_start_enum(int *nprinters_ptr)
ret->enum_level = 4; ret->enum_level = 4;
} }
retval = printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, if (!printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
ret->enum_level, buffer, 0, nprinters_ptr); ret->enum_level, &buffer, 0, nprinters_ptr))
if (!retval)
goto error; goto error;
else
buffer = retval;
switch (ret->enum_level) { switch (ret->enum_level) {
case 4: case 4:

View File

@ -180,6 +180,7 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
sa.bInheritHandle = TRUE; sa.bInheritHandle = TRUE;
if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) { if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
ret->error = dupprintf("Unable to create pipes for proxy command"); ret->error = dupprintf("Unable to create pipes for proxy command");
sfree(cmd);
return (Socket)ret; return (Socket)ret;
} }
@ -187,6 +188,7 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
CloseHandle(us_from_cmd); CloseHandle(us_from_cmd);
CloseHandle(cmd_to_us); CloseHandle(cmd_to_us);
ret->error = dupprintf("Unable to create pipes for proxy command"); ret->error = dupprintf("Unable to create pipes for proxy command");
sfree(cmd);
return (Socket)ret; return (Socket)ret;
} }

View File

@ -167,7 +167,10 @@ char *read_setting_s(void *handle, const char *key)
ret = snewn(size+1, char); ret = snewn(size+1, char);
if (RegQueryValueEx((HKEY) handle, key, 0, if (RegQueryValueEx((HKEY) handle, key, 0,
&type, ret, &size) != ERROR_SUCCESS || &type, ret, &size) != ERROR_SUCCESS ||
type != REG_SZ) return NULL; type != REG_SZ) {
sfree(ret);
return NULL;
}
return ret; return ret;
} }
@ -190,6 +193,7 @@ FontSpec *read_setting_fontspec(void *handle, const char *name)
{ {
char *settingname; char *settingname;
char *fontname; char *fontname;
FontSpec *ret;
int isbold, height, charset; int isbold, height, charset;
fontname = read_setting_s(handle, name); fontname = read_setting_s(handle, name);
@ -199,19 +203,30 @@ FontSpec *read_setting_fontspec(void *handle, const char *name)
settingname = dupcat(name, "IsBold", NULL); settingname = dupcat(name, "IsBold", NULL);
isbold = read_setting_i(handle, settingname, -1); isbold = read_setting_i(handle, settingname, -1);
sfree(settingname); sfree(settingname);
if (isbold == -1) return NULL; if (isbold == -1) {
sfree(fontname);
return NULL;
}
settingname = dupcat(name, "CharSet", NULL); settingname = dupcat(name, "CharSet", NULL);
charset = read_setting_i(handle, settingname, -1); charset = read_setting_i(handle, settingname, -1);
sfree(settingname); sfree(settingname);
if (charset == -1) return NULL; if (charset == -1) {
sfree(fontname);
return NULL;
}
settingname = dupcat(name, "Height", NULL); settingname = dupcat(name, "Height", NULL);
height = read_setting_i(handle, settingname, INT_MIN); height = read_setting_i(handle, settingname, INT_MIN);
sfree(settingname); sfree(settingname);
if (height == INT_MIN) return NULL; if (height == INT_MIN) {
sfree(fontname);
return NULL;
}
return fontspec_new(fontname, isbold, height, charset); ret = fontspec_new(fontname, isbold, height, charset);
sfree(fontname);
return ret;
} }
void write_setting_fontspec(void *handle, const char *name, FontSpec *font) void write_setting_fontspec(void *handle, const char *name, FontSpec *font)
@ -340,16 +355,18 @@ int verify_host_key(const char *hostname, int port,
* Now read a saved key in from the registry and see what it * Now read a saved key in from the registry and see what it
* says. * says.
*/ */
otherstr = snewn(len, char);
regname = snewn(3 * (strlen(hostname) + strlen(keytype)) + 15, char); regname = snewn(3 * (strlen(hostname) + strlen(keytype)) + 15, char);
hostkey_regname(regname, hostname, port, keytype); hostkey_regname(regname, hostname, port, keytype);
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys", if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
&rkey) != ERROR_SUCCESS) &rkey) != ERROR_SUCCESS) {
sfree(regname);
return 1; /* key does not exist in registry */ return 1; /* key does not exist in registry */
}
readlen = len; readlen = len;
otherstr = snewn(len, char);
ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen); ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen);
if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA && if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA &&
@ -412,6 +429,8 @@ int verify_host_key(const char *hostname, int port,
RegSetValueEx(rkey, regname, 0, REG_SZ, otherstr, RegSetValueEx(rkey, regname, 0, REG_SZ, otherstr,
strlen(otherstr) + 1); strlen(otherstr) + 1);
} }
sfree(oldstyle);
} }
RegCloseKey(rkey); RegCloseKey(rkey);