8000 Avoid fetching one past the end of translate()'s "to" parameter. · postgres/postgres@b1a9d8e · GitHub
[go: up one dir, main page]

Skip to content

Commit b1a9d8e

Browse files
committed
Avoid fetching one past the end of translate()'s "to" parameter.
This is usually harmless, but if you were very unlucky it could provoke a segfault due to the "to" string being right up against the end of memory. Found via valgrind testing (so we might've found it earlier, except that our regression tests lacked any exercise of translate()'s deletion feature). Fix by switching the order of the test-for-end-of-string and advance-pointer steps. While here, compute "to_ptr + tolen" just once. (Smarter compilers might figure that out for themselves, but let's just make sure.) Report and fix by Daniil Anisimov, in bug #17816. Discussion: https://postgr.es/m/17816-70f3d2764e88a108@postgresql.org
1 parent 73e779b commit b1a9d8e

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

src/backend/utils/adt/oracle_compat.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,8 @@ translate(PG_FUNCTION_ARGS)
723723
text *to = PG_GETARG_TEXT_PP(2);
724724
text *result;
725725
char *from_ptr,
726-
*to_ptr;
726+
*to_ptr,
727+
*to_end;
727728
char *source,
728729
*target;
729730
int m,
@@ -745,6 +746,7 @@ translate(PG_FUNCTION_ARGS)
745746
from_ptr = VARDATA_ANY(from);
746747
tolen = VARSIZE_ANY_EXHDR(to);
747748
to_ptr = VARDATA_ANY(to);
749+
to_end = to_ptr + tolen;
748750

749751
/*
750752
* The worst-case expansion is to substitute a max-length character for a
@@ -778,16 +780,16 @@ translate(PG_FUNCTION_ARGS)
778780
}
779781
if (i < fromlen)
780782
{
781-
/* substitute */
783+
/* substitute, or delete if no corresponding "to" character */
782784
char *p = to_ptr;
783785

784786
for (i = 0; i < from_index; i++)
785787
{
786-
p += pg_mblen(p);
787-
if (p >= (to_ptr + tolen))
788+
if (p >= to_end)
788789
break;
790+
p += pg_mblen(p);
789791
}
790-
if (p < (to_ptr + tolen))
792+
if (p < to_end)
791793
{
792794
len = pg_mblen(p);
793795
memcpy(target, p, len);

src/test/regress/expected/strings.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,12 @@ SELECT translate('12345', '14', 'ax');
17711771
a23x5
17721772
(1 row)
17731773

1774+
SELECT translate('12345', '134', 'a');
1775+
translate
1776+
-----------
1777+
a25
1778+
(1 row)
1779+
17741780
SELECT ascii('x');
17751781
ascii
17761782
-------

src/test/regress/sql/strings.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ SELECT ltrim('zzzytrim', 'xyz');
608608

609609
SELECT translate('', '14', 'ax');
610610
SELECT translate('12345', '14', 'ax');
611+
SELECT translate('12345', '134', 'a');
611612

612613
SELECT ascii('x');
613614
SELECT ascii('');

0 commit comments

Comments
 (0)
0