diff options
Diffstat (limited to 'Zend/zend_ini_scanner.l')
-rw-r--r-- | Zend/zend_ini_scanner.l | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index 6207c76b2..54c642c3a 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" @@ -137,9 +138,55 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals; Z_TYPE_P(retval) = IS_STRING; \ } -#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; + 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) @@ -172,7 +219,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; } @@ -422,10 +469,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(); |