From aaf15ee33a63c582fbb61b67befdd620e85da2ce Mon Sep 17 00:00:00 2001 From: Noah Misch Date: Wed, 8 Jul 2015 20:44:21 -0400 Subject: Revoke support for strxfrm() that write past the specified array length. This formalizes a decision implicit in commit 4ea51cdfe85ceef8afabceb03c446574daa0ac23 and adds clean detection of affected systems. Vendor updates are available for each such known bug. Back-patch to 9.5, where the aforementioned commit first appeared. --- src/backend/utils/adt/selfuncs.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'src/backend/utils/adt/selfuncs.c') diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 04ed07b762d..64b6ae4838f 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -3932,16 +3932,8 @@ convert_string_datum(Datum value, Oid typid) size_t xfrmlen2 PG_USED_FOR_ASSERTS_ONLY; /* - * Note: originally we guessed at a suitable output buffer size, and - * only needed to call strxfrm twice if our guess was too small. - * However, it seems that some versions of Solaris have buggy strxfrm - * that can write past the specified buffer length in that scenario. - * So, do it the dumb way for portability. - * - * Yet other systems (e.g., glibc) sometimes return a smaller value - * from the second call than the first; thus the Assert must be <= not - * == as you'd expect. Can't any of these people program their way - * out of a paper bag? + * XXX: We could guess at a suitable output buffer size and only call + * strxfrm twice if our guess is too small. * * XXX: strxfrm doesn't support UTF-8 encoding on Win32, it can return * bogus data or set an error. This is not really a problem unless it @@ -3974,6 +3966,11 @@ convert_string_datum(Datum value, Oid typid) #endif xfrmstr = (char *) palloc(xfrmlen + 1); xfrmlen2 = strxfrm(xfrmstr, val, xfrmlen + 1); + + /* + * Some systems (e.g., glibc) can return a smaller value from the + * second call than the first; thus the Assert must be <= not ==. + */ Assert(xfrmlen2 <= xfrmlen); pfree(val); val = xfrmstr; -- cgit v1.2.3