diff --git a/src/lib-sieve/sieve-lexer.c b/src/lib-sieve/sieve-lexer.c index f74a6746796e6f8f34bbef9da4eedb30209ff68f..19946530d7a1469338cb60a9bf1d125061718e72 100644 --- a/src/lib-sieve/sieve-lexer.c +++ b/src/lib-sieve/sieve-lexer.c @@ -272,6 +272,72 @@ static inline const char *_char_sanitize(int ch) return t_strdup_printf("0x%02x", ch); } +static bool +sieve_lexer_scan_number(struct sieve_lexical_scanner *scanner) +{ + struct sieve_lexer *lexer = &scanner->lexer; + uintmax_t value; + string_t *str; + bool overflow = FALSE; + + str_truncate(lexer->token_str_value,0); + str = lexer->token_str_value; + + while ( i_isdigit(sieve_lexer_curchar(scanner)) ) { + str_append_c(str, sieve_lexer_curchar(scanner)); + sieve_lexer_shift(scanner); + } + + if (str_to_uintmax(str_c(str), &value) < 0 || + value > (sieve_number_t)-1) { + overflow = TRUE; + } else { + switch ( sieve_lexer_curchar(scanner) ) { + case 'k': + case 'K': /* Kilo */ + if ( value > (SIEVE_MAX_NUMBER >> 10) ) + overflow = TRUE; + else + value = value << 10; + sieve_lexer_shift(scanner); + break; + case 'm': + case 'M': /* Mega */ + if ( value > (SIEVE_MAX_NUMBER >> 20) ) + overflow = TRUE; + else + value = value << 20; + sieve_lexer_shift(scanner); + break; + case 'g': + case 'G': /* Giga */ + if ( value > (SIEVE_MAX_NUMBER >> 30) ) + overflow = TRUE; + else + value = value << 30; + sieve_lexer_shift(scanner); + break; + default: + /* Next token */ + break; + } + } + + /* Check for integer overflow */ + if ( overflow ) { + sieve_lexer_error(lexer, + "number exceeds integer limits (max %llu)", + (long long) SIEVE_MAX_NUMBER); + lexer->token_type = STT_ERROR; + return FALSE; + } + + lexer->token_type = STT_NUMBER; + lexer->token_int_value = (sieve_number_t)value; + return TRUE; + +} + static bool sieve_lexer_scan_hash_comment(struct sieve_lexical_scanner *scanner) { @@ -537,65 +603,7 @@ sieve_lexer_scan_raw_token(struct sieve_lexical_scanner *scanner) default: /* number */ if ( i_isdigit(sieve_lexer_curchar(scanner)) ) { - sieve_number_t value = DIGIT_VAL(sieve_lexer_curchar(scanner)); - bool overflow = FALSE; - - sieve_lexer_shift(scanner); - - while ( i_isdigit(sieve_lexer_curchar(scanner)) ) { - sieve_number_t valnew = - value * 10 + DIGIT_VAL(sieve_lexer_curchar(scanner)); - - /* Check for integer wrap */ - if ( valnew < value ) - overflow = TRUE; - - value = valnew; - sieve_lexer_shift(scanner); - } - - switch ( sieve_lexer_curchar(scanner) ) { - case 'k': - case 'K': /* Kilo */ - if ( value > (SIEVE_MAX_NUMBER >> 10) ) - overflow = TRUE; - else - value = value << 10; - sieve_lexer_shift(scanner); - break; - case 'm': - case 'M': /* Mega */ - if ( value > (SIEVE_MAX_NUMBER >> 20) ) - overflow = TRUE; - else - value = value << 20; - sieve_lexer_shift(scanner); - break; - case 'g': - case 'G': /* Giga */ - if ( value > (SIEVE_MAX_NUMBER >> 30) ) - overflow = TRUE; - else - value = value << 30; - sieve_lexer_shift(scanner); - break; - default: - /* Next token */ - break; - } - - /* Check for integer wrap */ - if ( overflow ) { - sieve_lexer_error(lexer, - "number exceeds integer limits (max %llu)", - (long long) SIEVE_MAX_NUMBER); - lexer->token_type = STT_ERROR; - return FALSE; - } - - lexer->token_type = STT_NUMBER; - lexer->token_int_value = value; - return TRUE; + return sieve_lexer_scan_number(scanner); /* identifier / tag */ } else if ( i_isalpha(sieve_lexer_curchar(scanner)) ||