diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-05-12 11:56:38 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-05-12 11:57:26 -0400 |
commit | a7d3110638bd9b8951c11913621e86ac79db1a1f (patch) | |
tree | 27903cc3c32b2faeca7ac3f1c65e51cd269adc57 /src | |
parent | 7b9bbb68e38d9f39ec2b555b0b9aab9e50585c3e (diff) | |
download | postgresql-a7d3110638bd9b8951c11913621e86ac79db1a1f.tar.gz postgresql-a7d3110638bd9b8951c11913621e86ac79db1a1f.zip |
Fix write-past-buffer-end in ldapServiceLookup().
The code to assemble ldap_get_values_len's output into a single string
wrote the terminating null one byte past where it should. Fix that,
and make some other cosmetic adjustments to make the code a trifle more
readable and more in line with usual Postgres coding style.
Also, free the "result" string when done with it, to avoid a permanent
memory leak.
Bug report and patch by Albe Laurenz, cosmetic adjustments by me.
Diffstat (limited to 'src')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 5412ee606ff..58d70bd4d96 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -2648,10 +2648,11 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options, return 1; } - /* concatenate values to a single string */ - for (size = 0, i = 0; values[i] != NULL; ++i) + /* concatenate values into a single string with newline terminators */ + size = 1; /* for the trailing null */ + for (i = 0; values[i] != NULL; i++) size += values[i]->bv_len + 1; - if ((result = malloc(size + 1)) == NULL) + if ((result = malloc(size)) == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); @@ -2659,14 +2660,14 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options, ldap_unbind(ld); return 3; } - for (p = result, i = 0; values[i] != NULL; ++i) + p = result; + for (i = 0; values[i] != NULL; i++) { - strncpy(p, values[i]->bv_val, values[i]->bv_len); + memcpy(p, values[i]->bv_val, values[i]->bv_len); p += values[i]->bv_len; *(p++) = '\n'; - if (values[i + 1] == NULL) - *(p + 1) = '\0'; } + *p = '\0'; ldap_value_free_len(values); ldap_unbind(ld); @@ -2695,6 +2696,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options, printfPQExpBuffer(errorMessage, libpq_gettext( "missing \"=\" after \"%s\" in connection info string\n"), optname); + free(result); return 3; } else if (*p == '=') @@ -2713,6 +2715,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options, printfPQExpBuffer(errorMessage, libpq_gettext( "missing \"=\" after \"%s\" in connection info string\n"), optname); + free(result); return 3; } break; @@ -2776,6 +2779,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options, printfPQExpBuffer(errorMessage, libpq_gettext("invalid connection option \"%s\"\n"), optname); + free(result); return 1; } optname = NULL; @@ -2784,6 +2788,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options, oldstate = state; } + free(result); + if (state == 5 || state == 6) { printfPQExpBuffer(errorMessage, libpq_gettext( |