Skip to content

Commit ccd3623

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 7deeb02 commit ccd3623

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
@@ -727,16 +727,14 @@ _soundex(const char *instr, char *outstr)
727727
AssertArg(instr);
728728
AssertArg(outstr);
729729

730-
outstr[SOUNDEX_LEN] = '\0';
731-
732730
/* Skip leading non-alphabetic characters */
733-
while (!isalpha((unsigned char) instr[0]) && instr[0])
731+
while (*instr && !isalpha((unsigned char) *instr))
734732
++instr;
735733

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

@@ -749,7 +747,7 @@ _soundex(const char *instr, char *outstr)
749747
if (isalpha((unsigned char) *instr) &&
750748
soundex_code(*instr) != soundex_code(*(instr - 1)))
751749
{
752-
*outstr = soundex_code(instr[0]);
750+
*outstr = soundex_code(*instr);
753751
if (*outstr != '0')
754752
{
755753
++outstr;
@@ -766,6 +764,9 @@ _soundex(const char *instr, char *outstr)
766764
++outstr;
767765
++count;
768766
}
767+
768+
/* And null-terminate */
769+
*outstr = '\0';
769770
}
770771

771772
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)