Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1d369c9

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 27debd0 commit 1d369c9

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

contrib/fuzzystrmatch/expected/fuzzystrmatch.out

+6
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

+8-7
Original file line numberDiff line numberDiff line change
@@ -728,16 +728,14 @@ _soundex(const char *instr, char *outstr)
728728
Assert(instr);
729729
Assert(outstr);
730730

731-
outstr[SOUNDEX_LEN] = '\0';
732-
733731
/* Skip leading non-alphabetic characters */
734-
while (!isalpha((unsigned char) instr[0]) && instr[0])
732+
while (*instr && !isalpha((unsigned char) *instr))
735733
++instr;
736734

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

@@ -750,7 +748,7 @@ _soundex(const char *instr, char *outstr)
750748
if (isalpha((unsigned char) *instr) &&
751749
soundex_code(*instr) != soundex_code(*(instr - 1)))
752750
{
753-
*outstr = soundex_code(instr[0]);
751+
*outstr = soundex_code(*instr);
754752
if (*outstr != '0')
755753
{
756754
++outstr;
@@ -767,6 +765,9 @@ _soundex(const char *instr, char *outstr)
767765
++outstr;
768766
++count;
769767
}
768+
769+
/* And null-terminate */
770+
*outstr = '\0';
770771
}
771772

772773
PG_FUNCTION_INFO_V1(difference);

contrib/fuzzystrmatch/sql/fuzzystrmatch.sql

+1
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)