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

Commit 3a02d68

Browse files
committed
Avoid divide-by-zero in regex_selectivity() with long fixed prefix.
Given a regex pattern with a very long fixed prefix (approaching 500 characters), the result of pow(FIXED_CHAR_SEL, fixed_prefix_len) can underflow to zero. Typically the preceding selectivity calculation would have underflowed as well, so that we compute 0/0 and get NaN. In released branches this leads to an assertion failure later on. That doesn't happen in HEAD, for reasons I've not explored yet, but it's surely still a bug. To fix, just skip the division when the pow() result is zero, so that we'll (most likely) return a zero selectivity estimate. In the edge cases where "sel" didn't yet underflow, perhaps this isn't desirable, but I'm not sure that the case is worth spending a lot of effort on. The results of regex_selectivity_sub() are barely worth the electrons they're written on anyway :-( Per report from Alexander Lakhin. Back-patch to all supported versions. Discussion: https://postgr.es/m/6de0a0c3-ada9-cd0c-3e4e-2fa9964b41e3@gmail.com
1 parent c6cd20d commit 3a02d68

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/backend/utils/adt/like_support.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -1442,9 +1442,18 @@ regex_selectivity(const char *patt, int pattlen, bool case_insensitive,
14421442
sel *= FULL_WILDCARD_SEL;
14431443
}
14441444

1445-
/* If there's a fixed prefix, discount its selectivity */
1445+
/*
1446+
* If there's a fixed prefix, discount its selectivity. We have to be
1447+
* careful here since a very long prefix could result in pow's result
1448+
* underflowing to zero (in which case "sel" probably has as well).
1449+
*/
14461450
if (fixed_prefix_len > 0)
1447-
sel /= pow(FIXED_CHAR_SEL, fixed_prefix_len);
1451+
{
1452+
double prefixsel = pow(FIXED_CHAR_SEL, fixed_prefix_len);
1453+
1454+
if (prefixsel > 0.0)
1455+
sel /= prefixsel;
1456+
}
14481457

14491458
/* Make sure result stays in range */
14501459
CLAMP_PROBABILITY(sel);

0 commit comments

Comments
 (0)