summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2018-11-15 10:56:31 -0700
committerKarl Williamson <khw@cpan.org>2018-11-17 10:02:11 -0700
commit1d8aafa0548097ffe407cad078f79b4d56fd7dca (patch)
tree5d9739d91a092f3ca1b7346a7069b340c72a0a4d
parent012b274eec07a4c9eeea66cdccf68990e896323d (diff)
downloadperl-1d8aafa0548097ffe407cad078f79b4d56fd7dca.tar.gz
regexec.c: Fix logic error
The function S_find_next_masked() could return a pointer to something that wasn't wanted, returning prematurely due to a logic error I made. This erroneous code is in 5.28.0, but I couldn't figure out any actual bugs this caused, due to the circumstances it is called under. The bug is I should have used 'xor' instead of complement and 'and'. Thus trying to find 0x2f, with a mask of all F's also found 2e.
-rw-r--r--regexec.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/regexec.c b/regexec.c
index 1b1ded8a24..334536917a 100644
--- a/regexec.c
+++ b/regexec.c
@@ -749,7 +749,7 @@ S_find_next_masked(U8 * s, const U8 * send, const U8 byte, const U8 mask)
+ PERL_WORDSIZE * PERL_IS_SUBWORD_ADDR(s)
- (PTR2nat(s) & PERL_WORD_BOUNDARY_MASK))
{
- PERL_UINTMAX_T word_complemented, mask_word;
+ PERL_UINTMAX_T word, mask_word;
while (PTR2nat(s) & PERL_WORD_BOUNDARY_MASK) {
if (((*s) & mask) == byte) {
@@ -758,15 +758,17 @@ S_find_next_masked(U8 * s, const U8 * send, const U8 byte, const U8 mask)
s++;
}
- word_complemented = ~ (PERL_COUNT_MULTIPLIER * byte);
- mask_word = PERL_COUNT_MULTIPLIER * mask;
+ word = PERL_COUNT_MULTIPLIER * byte;
+ mask_word = PERL_COUNT_MULTIPLIER * mask;
do {
PERL_UINTMAX_T masked = (* (PERL_UINTMAX_T *) s) & mask_word;
- /* If 'masked' contains 'byte' within it, anding with the
- * complement will leave those 8 bits 0 */
- masked &= word_complemented;
+ /* If 'masked' contains bytes with the bit pattern of 'byte' within
+ * it, xoring with 'word' will leave each of the 8 bits in such
+ * bytes be 0, and no byte containing any other bit pattern will be
+ * 0. */
+ masked ^= word;
/* This causes the most significant bit to be set to 1 for any
* bytes in the word that aren't completely 0 */