Skip to content

Commit 0966291

Browse files
committed
Ensure Soundex difference() function handles empty input sanely.
fuzzystrmatch's difference() function assumes that _soundex() always initializes its output buffer fully. This was not so for the case of a string containing no alphabetic characters, resulting in unstable output and Valgrind complaints. Fix by using memset() to fill the whole buffer in the early-exit case. Also make some cosmetic improvements (I didn't care for the random switches between "instr[0]" and "*instr" notation). Report and diagnosis by Alexander Lakhin (bug #17935). Back-patch to all supported branches. Discussion: https://postgr.es/m/17935-b99316aa79c18513@postgresql.org
1 parent 3282e07 commit 0966291

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

contrib/fuzzystrmatch/expected/fuzzystrmatch.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ SELECT soundex('Anne'), soundex('Margaret'), difference('Anne', 'Margaret');
2323
A500 | M626 | 0
2424
(1 row)
2525

26+
SELECT soundex(''), difference('', '');
27+
soundex | difference
28+
---------+------------
29+
| 4
30+
(1 row)
31+
2632
SELECT levenshtein('GUMBO', 'GAMBOL');
2733
levenshtein
2834
-------------

contrib/fuzzystrmatch/fuzzystrmatch.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -729,16 +729,14 @@ _soundex(const char *instr, char *outstr)
729729
AssertArg(instr);
730730
AssertArg(outstr);
731731

732-
outstr[SOUNDEX_LEN] = '\0';
733-
734732
/* Skip leading non-alphabetic characters */
735-
while (!isalpha((unsigned char) instr[0]) && instr[0])
733+
while (*instr && !isalpha((unsigned char) *instr))
736734
++instr;
737735

738-
/* No string left */
739-
if (!instr[0])
736+
/* If no string left, return all-zeroes buffer */
737+
if (!*instr)
740738
{
741-
outstr[0] = (char) 0;
739+
memset(outstr, '\0', SOUNDEX_LEN + 1);
742740
return;
743741
}
744742

@@ -751,7 +749,7 @@ _soundex(const char *instr, char *outstr)
751749
if (isalpha((unsigned char) *instr) &&
752750
soundex_code(*instr) != soundex_code(*(instr - 1)))
753751
{
754-
*outstr = soundex_code(instr[0]);
752+
*outstr = soundex_code(*instr);
755753
if (*outstr != '0')
756754
{
757755
++outstr;
@@ -768,6 +766,9 @@ _soundex(const char *instr, char *outstr)
768766
++outstr;
769767
++count;
770768
}
769+
770+
/* And null-terminate */
771+
*outstr = '\0';
771772
}
772773

773774
PG_FUNCTION_INFO_V1(difference);

contrib/fuzzystrmatch/sql/fuzzystrmatch.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ SELECT soundex('hello world!');
66
SELECT soundex('Anne'), soundex('Ann'), difference('Anne', 'Ann');
77
SELECT soundex('Anne'), soundex('Andrew'), difference('Anne', 'Andrew');
88
SELECT soundex('Anne'), soundex('Margaret'), difference('Anne', 'Margaret');
9+
SELECT soundex(''), difference('', '');
910

1011

1112
SELECT levenshtein('GUMBO', 'GAMBOL');

0 commit comments

Comments
 (0)