This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix the PEEK_INFNAN (wrong macro arg name).
authorJarkko Hietaniemi <jhi@iki.fi>
Fri, 22 Aug 2014 18:52:46 +0000 (14:52 -0400)
committerJarkko Hietaniemi <jhi@iki.fi>
Fri, 22 Aug 2014 19:18:49 +0000 (15:18 -0400)
Also rename as INFNAN_PEEK, to match HEXFP_PEEK.

Add "send" pointer to INFNAN_PEEK to guard againt past-the-buffer peeking.

HEXFP_PEEK doesn't easily lend itself to "send" pointer
because of it's calling environment doesn't have one.

numeric.c
toke.c

index ce8bbdd..26d795c 100644 (file)
--- a/numeric.c
+++ b/numeric.c
@@ -587,11 +587,14 @@ Perl_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep)
 }
 
 /* Peek ahead to see whether this could be Inf/NaN/qNaN/snan/1.#INF */
-#define PEEK_INFNAN(d) \
-    (isALPHA_FOLD_EQ(*s, 'I') || isALPHA_FOLD_EQ(*s, 'N')) || \
-     ((isALPHA_FOLD_EQ(*s, 'Q') || isALPHA_FOLD_EQ(*s, 'S')) && \
-      isALPHA_FOLD_EQ(s[1], 'N')) || \
-    (*s == '1' && ((s[1] == '.' && s[2] == '#') || s[1] == '#'))
+#define INFNAN_PEEK(s, send) \
+    (s < send && \
+     ((isALPHA_FOLD_EQ(*s, 'I') || isALPHA_FOLD_EQ(*s, 'N')) ||  \
+      ((s + 4) < send &&                                         \
+       (isALPHA_FOLD_EQ(*s, 'Q') || isALPHA_FOLD_EQ(*s, 'S')) && \
+       isALPHA_FOLD_EQ(s[1], 'N')) || \
+      ((s + 5) < send &&                                                \
+       (*s == '1' && ((s[1] == '.' && s[2] == '#') || s[1] == '#')))))
 
 /*
 =for apidoc grok_infnan
@@ -839,7 +842,7 @@ Perl_grok_number_flags(pTHX_ const char *pv, STRLEN len, UV *valuep, U32 flags)
         return 0;
   }
   else {
-      if (PEEK_INFNAN(d)) {
+      if (INFNAN_PEEK(d, send)) {
           int infnan = Perl_grok_infnan(&d, send);
           if ((infnan & IS_NUMBER_INFINITY)) {
               numtype |= infnan;
@@ -1184,9 +1187,9 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
             }
         }
 #elif defined(HAS_STRTOD)
-        if (PEEK_INFNAN(s)) {
+        if (INFNAN_PEEK(s, send)) {
             /* The native strtod() may not get all the possible
-             * inf/nan strings PEEK_INFNAN() recognizes. */
+             * inf/nan strings INFNAN_PEEK() recognizes. */
             char* endp;
             NV nv = Perl_strtod(p, &endp);
             if (p != endp) {
diff --git a/toke.c b/toke.c
index dee6f42..f855f69 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -114,6 +114,11 @@ static const char* const ident_too_long = "Identifier too long";
 
 #define SPACE_OR_TAB(c) isBLANK_A(c)
 
+#define HEXFP_PEEK(s)     \
+    (((s[0] == '.') && \
+      (isXDIGIT(s[1]) || isALPHA_FOLD_EQ(s[1], 'p'))) || \
+     isALPHA_FOLD_EQ(s[0], 'p'))
+
 /* LEX_* are values for PL_lex_state, the state of the lexer.
  * They are arranged oddly so that the guard on the switch statement
  * can get by with a single comparison (if the compiler is smart enough).
@@ -9980,10 +9985,6 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
 
                     /* this could be hexfp, but peek ahead
                      * to avoid matching ".." */
-#define HEXFP_PEEK(s) \
-       (((s[0] == '.') && \
-         (isXDIGIT(s[1]) || isALPHA_FOLD_EQ(s[1], 'p'))) \
-        || isALPHA_FOLD_EQ(s[0], 'p'))
                     if (UNLIKELY(HEXFP_PEEK(s))) {
                         goto out;
                     }