summaryrefslogtreecommitdiffstats
path: root/src/glsl/pp/sl_pp_token.c
diff options
context:
space:
mode:
authorMichal Krol <[email protected]>2009-09-16 21:51:12 +0200
committerMichal Krol <[email protected]>2009-09-16 21:51:12 +0200
commita7382628f2ed5a2886a1828dd847d75bf8e9b38e (patch)
tree72c2b19c8018103937e758de5c93ff7d7dcd4ddb /src/glsl/pp/sl_pp_token.c
parentde0753e4cb64792d257ad3799932a77321fc3c49 (diff)
glsl/pp: Validate numbers.
Diffstat (limited to 'src/glsl/pp/sl_pp_token.c')
-rw-r--r--src/glsl/pp/sl_pp_token.c250
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 95fe4f7d85e..a6a2bb27485 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;
}