Fix write-past-buffer-end in ldapServiceLookup().
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 May 2011 15:56:38 +0000 (11:56 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 May 2011 15:57:26 +0000 (11:57 -0400)
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.

src/interfaces/libpq/fe-connect.c

index 5412ee606ffc9bf24905d62c37b5979b11de3e3b..58d70bd4d965eb469b65c50b08e94066c40d19d8 100644 (file)
@@ -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(