diff options
Diffstat (limited to 'Zend/zend_ini_scanner.l')
-rw-r--r-- | Zend/zend_ini_scanner.l | 65 |
1 files changed, 58 insertions, 7 deletions
diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index bbc48d1fc1..3bfb1557b1 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -24,6 +24,7 @@ #include <errno.h> #include "zend.h" +#include "zend_API.h" #include "zend_globals.h" #include <zend_ini_parser.h> #include "zend_ini_scanner.h" @@ -132,12 +133,58 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals; #define EAT_TRAILING_WHITESPACE() EAT_TRAILING_WHITESPACE_EX('X') #define zend_ini_copy_value(retval, str, len) \ - ZVAL_NEW_STR(retval, STR_INIT(str, len, 1)) + ZVAL_NEW_STR(retval, zend_string_init(str, len, 1)) -#define RETURN_TOKEN(type, str, len) { \ - zend_ini_copy_value(ini_lval, str, len); \ - return type; \ +#define RETURN_TOKEN(type, str, len) { \ + if (SCNG(scanner_mode) == ZEND_INI_SCANNER_TYPED) { \ + zend_ini_copy_typed_value(ini_lval, type, str, len); \ + } else { \ + zend_ini_copy_value(ini_lval, str, len); \ + } \ + return type; \ +} + +static inline int convert_to_number(zval *retval, const char *str, const int str_len) +{ + zend_uchar type; + int overflow; + zend_long lval; + double dval; + + if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow)) != 0) { + if (type == IS_LONG) { + ZVAL_LONG(retval, lval); + return SUCCESS; + } else if (type == IS_DOUBLE && !overflow) { + ZVAL_DOUBLE(retval, dval); + return SUCCESS; + } + } + + return FAILURE; +} + +static void zend_ini_copy_typed_value(zval *retval, const int type, const char *str, int len) +{ + switch (type) { + case BOOL_FALSE: + case BOOL_TRUE: + ZVAL_BOOL(retval, type == BOOL_TRUE); + break; + + case NULL_NULL: + ZVAL_NULL(retval); + break; + + case TC_NUMBER: + if (convert_to_number(retval, str, len) == SUCCESS) { + break; + } + /* intentional fall-through */ + default: + zend_ini_copy_value(retval, str, len); + } } static void _yy_push_state(int new_state TSRMLS_DC) @@ -169,7 +216,7 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC) static int init_ini_scanner(int scanner_mode, zend_file_handle *fh TSRMLS_DC) { /* Sanity check */ - if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW) { + if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW && scanner_mode != ZEND_INI_SCANNER_TYPED) { zend_error(E_WARNING, "Invalid scanner mode"); return FAILURE; } @@ -419,10 +466,14 @@ SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR}) RETURN_TOKEN(BOOL_TRUE, "1", 1); } -<INITIAL,ST_VALUE>("false"|"off"|"no"|"none"|"null"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/ +<INITIAL,ST_VALUE>("false"|"off"|"no"|"none"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/ RETURN_TOKEN(BOOL_FALSE, "", 0); } +<INITIAL,ST_VALUE>("null"){TABS_AND_SPACES}* { + RETURN_TOKEN(NULL_NULL, "", 0); +} + <INITIAL>{LABEL} { /* Get option name */ /* Eat leading whitespace */ EAT_LEADING_WHITESPACE(); @@ -443,7 +494,7 @@ SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR}) } <ST_RAW>{RAW_VALUE_CHARS} { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */ - char *sc = NULL; + unsigned char *sc = NULL; while (YYCURSOR < YYLIMIT) { switch (*YYCURSOR) { case '\n': |