Mesa (glsl-pp-rework-2): glsl/pp: Validate numbers.

Michał Król michal at kemper.freedesktop.org
Wed Sep 16 20:04:33 UTC 2009


Module: Mesa
Branch: glsl-pp-rework-2
Commit: a7382628f2ed5a2886a1828dd847d75bf8e9b38e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a7382628f2ed5a2886a1828dd847d75bf8e9b38e

Author: Michal Krol <michal at vmware.com>
Date:   Wed Sep 16 21:51:12 2009 +0200

glsl/pp: Validate numbers.

---

 src/glsl/pp/sl_pp_token.c |  250 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 227 insertions(+), 23 deletions(-)

diff --git a/src/glsl/pp/sl_pp_token.c b/src/glsl/pp/sl_pp_token.c
index 95fe4f7..a6a2bb2 100644
--- a/src/glsl/pp/sl_pp_token.c
+++ b/src/glsl/pp/sl_pp_token.c
@@ -30,6 +30,13 @@
 
 
 static int
+_is_identifier_char(char c)
+{
+   return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+}
+
+
+static int
 _tokenise_identifier(struct sl_pp_context *context,
                      const char **pinput,
                      struct sl_pp_token_info *info)
@@ -42,10 +49,7 @@ _tokenise_identifier(struct sl_pp_context *context,
    info->data.identifier = -1;
 
    identifier[i++] = *input++;
-   while ((*input >= 'a' && *input <= 'z') ||
-          (*input >= 'A' && *input <= 'Z') ||
-          (*input >= '0' && *input <= '9') ||
-          (*input == '_')) {
+   while (_is_identifier_char(*input)) {
       if (i >= sizeof(identifier) - 1) {
          strcpy(context->error_msg, "out of memory");
          return -1;
@@ -64,41 +68,241 @@ _tokenise_identifier(struct sl_pp_context *context,
 }
 
 
+/*
+ * Return the number of consecutive decimal digits in the input stream.
+ */
+static unsigned int
+_parse_float_digits(const char *input)
+{
+   unsigned int eaten = 0;
+
+   while (input[eaten] >= '0' && input[eaten] <= '9') {
+      eaten++;
+   }
+   return eaten;
+}
+
+
+/*
+ * Try to match one of the following patterns for the fractional part
+ * of a floating point number.
+ *
+ * digits . [digits]
+ * . digits
+ *
+ * Return 0 if the pattern could not be matched, otherwise the number
+ * of eaten characters from the input stream.
+ */
+static unsigned int
+_parse_float_frac(const char *input)
+{
+   unsigned int eaten;
+
+   if (input[0] == '.') {
+      eaten = _parse_float_digits(&input[1]);
+      if (eaten) {
+         return eaten + 1;
+      }
+      return 0;
+   }
+
+   eaten = _parse_float_digits(input);
+   if (eaten && input[eaten] == '.') {
+      unsigned int trailing;
+
+      trailing = _parse_float_digits(&input[eaten + 1]);
+      if (trailing) {
+         return eaten + trailing + 1;
+      }
+      return eaten + 1;
+   }
+
+   return 0;
+}
+
+
+/*
+ * Try to match the following pattern for the exponential part
+ * of a floating point number.
+ *
+ * (e|E) [(+|-)] digits
+ *
+ * Return 0 if the pattern could not be matched, otherwise the number
+ * of eaten characters from the input stream.
+ */
+static unsigned int
+_parse_float_exp(const char *input)
+{
+   unsigned int eaten, digits;
+
+   if (input[0] != 'e' && input[0] != 'E') {
+      return 0;
+   }
+
+   if (input[1] == '-' || input[1] == '+') {
+      eaten = 2;
+   } else {
+      eaten = 1;
+   }
+
+   digits = _parse_float_digits(&input[eaten]);
+   if (!digits) {
+      return 0;
+   }
+
+   return eaten + digits;
+}
+
+
+/*
+ * Try to match one of the following patterns for a floating point number.
+ *
+ * fract [exp] [(f|F)]
+ * digits exp [(f|F)]
+ *
+ * Return 0 if the pattern could not be matched, otherwise the number
+ * of eaten characters from the input stream.
+ */
+static unsigned int
+_parse_float(const char *input)
+{
+   unsigned int eaten;
+
+   eaten = _parse_float_frac(input);
+   if (eaten) {
+      unsigned int exponent;
+
+      exponent = _parse_float_exp(&input[eaten]);
+      if (exponent) {
+         eaten += exponent;
+      }
+
+      if (input[eaten] == 'f' || input[eaten] == 'F') {
+         eaten++;
+      }
+
+      return eaten;
+   }
+
+   eaten = _parse_float_digits(input);
+   if (eaten) {
+      unsigned int exponent;
+
+      exponent = _parse_float_exp(&input[eaten]);
+      if (exponent) {
+         eaten += exponent;
+
+         if (input[eaten] == 'f' || input[eaten] == 'F') {
+            eaten++;
+         }
+
+         return eaten;
+      }
+   }
+
+   return 0;
+}
+
+
+static unsigned int
+_parse_hex(const char *input)
+{
+   unsigned int n;
+
+   if (input[0] != '0') {
+      return 0;
+   }
+
+   if (input[1] != 'x' && input[1] != 'X') {
+      return 0;
+   }
+
+   n = 2;
+   while ((input[n] >= '0' && input[n] <= '9') ||
+          (input[n] >= 'a' && input[n] <= 'f') ||
+          (input[n] >= 'A' && input[n] <= 'F')) {
+      n++;
+   }
+
+   if (n > 2) {
+      return n;
+   }
+
+   return 0;
+}
+
+
+static unsigned int
+_parse_oct(const char *input)
+{
+   unsigned int n;
+
+   if (input[0] != '0') {
+      return 0;
+   }
+
+   n = 1;
+   while ((input[n] >= '0' && input[n] <= '7')) {
+      n++;
+   }
+
+   return n;
+}
+
+
+static unsigned int
+_parse_dec(const char *input)
+{
+   unsigned int n = 0;
+
+   while ((input[n] >= '0' && input[n] <= '9')) {
+      n++;
+   }
+
+   return n;
+}
+
+
 static int
 _tokenise_number(struct sl_pp_context *context,
                  const char **pinput,
                  struct sl_pp_token_info *info)
 {
    const char *input = *pinput;
+   unsigned int eaten;
    char number[256];   /* XXX: Remove this artifical limit. */
-   unsigned int i = 0;
 
-   info->token = SL_PP_NUMBER;
-   info->data.number = -1;
-
-   number[i++] = *input++;
-   while ((*input >= '0' && *input <= '9') ||
-          (*input >= 'a' && *input <= 'f') ||
-          (*input >= 'A' && *input <= 'F') ||
-          (*input == 'x') ||
-          (*input == 'X') ||
-          (*input == '+') ||
-          (*input == '-') ||
-          (*input == '.')) {
-      if (i >= sizeof(number) - 1) {
-         strcpy(context->error_msg, "out of memory");
-         return -1;
+   eaten = _parse_float(input);
+   if (!eaten) {
+      eaten = _parse_hex(input);
+      if (!eaten) {
+         eaten = _parse_oct(input);
+         if (!eaten) {
+            eaten = _parse_dec(input);
+         }
       }
-      number[i++] = *input++;
    }
-   number[i++] = '\0';
 
+   if (!eaten || _is_identifier_char(input[eaten])) {
+      strcpy(context->error_msg, "expected a number");
+      return -1;
+   }
+
+   if (eaten > sizeof(number) - 1) {
+      strcpy(context->error_msg, "out of memory");
+      return -1;
+   }
+
+   memcpy(number, input, eaten);
+   number[eaten] = '\0';
+
+   info->token = SL_PP_NUMBER;
    info->data.number = sl_pp_context_add_unique_str(context, number);
    if (info->data.number == -1) {
       return -1;
    }
 
-   *pinput = input;
+   *pinput = input + eaten;
    return 0;
 }
 




More information about the mesa-commit mailing list