This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
handy.h: Add bounds checking to case change arrays
authorKarl Williamson <public@khwilliamson.com>
Wed, 1 Sep 2010 02:20:01 +0000 (20:20 -0600)
committerRafael Garcia-Suarez <rgs@consttype.org>
Mon, 13 Sep 2010 11:56:03 +0000 (13:56 +0200)
This makes sure that the index into the arrays used to change between
lower and upper case will fit into their bounds; returning an error
character if not.  The check is likely to be optimized out if the index
is stored in 8 bits.

handy.h

diff --git a/handy.h b/handy.h
index b46b844..a1d753d 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -528,9 +528,7 @@ patched there.  The file as of this writing is cpan/Devel-PPPort/parts/inc/misc
 #   define isPUNCT(c)  ispunct(c)
 #   define isXDIGIT(c) isxdigit(c)
 #   define toUPPER(c)  toupper(c)
-#   define toUPPER_LATIN1_MOD(c)    UNI_TO_NATIVE(PL_mod_latin1_uc[(U8) NATIVE_TO_UNI(c)])
 #   define toLOWER(c)  tolower(c)
-#   define toLOWER_LATIN1(c)   UNI_TO_NATIVE(PL_latin1_lc[(U8) NATIVE_TO_UNI(c)])
 #else
 #   define isUPPER(c)  ((c) >= 'A' && (c) <= 'Z')
 #   define isLOWER(c)  ((c) >= 'a' && (c) <= 'z')
@@ -542,12 +540,20 @@ patched there.  The file as of this writing is cpan/Devel-PPPort/parts/inc/misc
 #   define isPUNCT(c)  (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64)  || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126))
 #   define isXDIGIT(c)  (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
 
-/* Use table lookup for speed */
-#   define toLOWER_LATIN1(c)   (PL_latin1_lc[(U8) c])
 
-/* Modified uc.  Is correct uc except for three non-ascii chars which are
- * all mapped to one of them, and these need special handling */
-#   define toUPPER_LATIN1_MOD(c)    (PL_mod_latin1_uc[(U8) c])
+    /* Use table lookup for speed; return error character for input
+     * out-of-range */
+#   define toLOWER_LATIN1(c)    (FITS_IN_8_BITS(c)                            \
+                                ? UNI_TO_NATIVE(PL_latin1_lc[                 \
+                                                  NATIVE_TO_UNI( (U8) (c)) ]) \
+                                : UNICODE_REPLACEMENT)
+    /* Modified uc.  Is correct uc except for three non-ascii chars which are
+     * all mapped to one of them, and these need special handling; error
+     * character for input out-of-range */
+#   define toUPPER_LATIN1_MOD(c) (FITS_IN_8_BITS(c)                           \
+                                 ? UNI_TO_NATIVE(PL_mod_latin1_uc[            \
+                                                  NATIVE_TO_UNI( (U8) (c)) ]) \
+                                 : UNICODE_REPLACEMENT)
 
 /* ASCII casing. */
 #   define toUPPER(c)  (isLOWER(c) ? (c) - ('a' - 'A') : (c))