aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-05-12 11:56:38 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-05-12 11:57:26 -0400
commita7d3110638bd9b8951c11913621e86ac79db1a1f (patch)
tree27903cc3c32b2faeca7ac3f1c65e51cd269adc57
parent7b9bbb68e38d9f39ec2b555b0b9aab9e50585c3e (diff)
downloadpostgresql-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.
-rw-r--r--src/interfaces/libpq/fe-connect.c20
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(