diff options
| author | Thibault "bui" Koechlin | 2017-12-28 17:04:06 +0100 |
|---|---|---|
| committer | jvoisin | 2017-12-28 17:04:06 +0100 |
| commit | 9f5e8d12f05fb24c915a5266a1e908a75c8aed08 (patch) | |
| tree | 9160075ea943c7fd29a3923f844a0ac0d6b8b457 | |
| parent | 62c48bf9a85e0294b7b32cea438e904e1cd50669 (diff) | |
Clang-format pass
- `clang-format --style="{BasedOnStyle: google, SortIncludes: false}" -i snuffleu*.c sp_*.c sp_*.h`
- Update the documentation accordingly
| -rw-r--r-- | CONTRIBUTING.md | 2 | ||||
| -rw-r--r-- | src/snuffleupagus.c | 91 | ||||
| -rw-r--r-- | src/sp_config.c | 61 | ||||
| -rw-r--r-- | src/sp_config.h | 13 | ||||
| -rw-r--r-- | src/sp_config_keywords.c | 66 | ||||
| -rw-r--r-- | src/sp_config_keywords.h | 8 | ||||
| -rw-r--r-- | src/sp_config_utils.c | 14 | ||||
| -rw-r--r-- | src/sp_cookie_encryption.c | 79 | ||||
| -rw-r--r-- | src/sp_cookie_encryption.h | 3 | ||||
| -rw-r--r-- | src/sp_disabled_functions.c | 95 | ||||
| -rw-r--r-- | src/sp_disabled_functions.h | 5 | ||||
| -rw-r--r-- | src/sp_execute.c | 68 | ||||
| -rw-r--r-- | src/sp_list.c | 17 | ||||
| -rw-r--r-- | src/sp_list.h | 3 | ||||
| -rw-r--r-- | src/sp_network_utils.c | 6 | ||||
| -rw-r--r-- | src/sp_unserialize.c | 33 | ||||
| -rw-r--r-- | src/sp_upload_validation.c | 5 | ||||
| -rw-r--r-- | src/sp_upload_validation.h | 3 | ||||
| -rw-r--r-- | src/sp_utils.c | 132 | ||||
| -rw-r--r-- | src/sp_utils.h | 25 | ||||
| -rw-r--r-- | src/sp_var_parser.c | 102 | ||||
| -rw-r--r-- | src/sp_var_value.c | 102 |
22 files changed, 496 insertions, 437 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 34cfd02..f8e8f37 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md | |||
| @@ -58,7 +58,7 @@ launching it, in order to run the failing test inside GDB. | |||
| 58 | 58 | ||
| 59 | Your patch should follow the same conventions & pass the same code quality | 59 | Your patch should follow the same conventions & pass the same code quality |
| 60 | checks as the rest of the project. We're using [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to | 60 | checks as the rest of the project. We're using [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to |
| 61 | ensure a consistent code-style. Please run it with `clang-format -style=google` | 61 | ensure a consistent code-style. Please run it with `clang-format --style="{BasedOnStyle: google, SortIncludes: false}"` |
| 62 | before committing, or even better, use a [pre-commit hook](https://github.com/andrewseidl/githook-clang-format). | 62 | before committing, or even better, use a [pre-commit hook](https://github.com/andrewseidl/githook-clang-format). |
| 63 | 63 | ||
| 64 | ### 6. Make a Pull Request | 64 | ### 6. Make a Pull Request |
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index b823a87..dd2d941 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -30,7 +30,7 @@ ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | |||
| 30 | 30 | ||
| 31 | PHP_INI_BEGIN() | 31 | PHP_INI_BEGIN() |
| 32 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, | 32 | PHP_INI_ENTRY("sp.configuration_file", "", PHP_INI_SYSTEM, |
| 33 | OnUpdateConfiguration) | 33 | OnUpdateConfiguration) |
| 34 | PHP_INI_END() | 34 | PHP_INI_END() |
| 35 | 35 | ||
| 36 | ZEND_DLEXPORT zend_extension zend_extension_entry = { | 36 | ZEND_DLEXPORT zend_extension zend_extension_entry = { |
| @@ -41,22 +41,22 @@ ZEND_DLEXPORT zend_extension zend_extension_entry = { | |||
| 41 | PHP_SNUFFLEUPAGUS_COPYRIGHT, | 41 | PHP_SNUFFLEUPAGUS_COPYRIGHT, |
| 42 | sp_zend_startup, | 42 | sp_zend_startup, |
| 43 | NULL, | 43 | NULL, |
| 44 | NULL, /* activate_func_t */ | 44 | NULL, /* activate_func_t */ |
| 45 | NULL, /* deactivate_func_t */ | 45 | NULL, /* deactivate_func_t */ |
| 46 | NULL, /* message_handler_func_t */ | 46 | NULL, /* message_handler_func_t */ |
| 47 | sp_op_array_handler,//zend_global_strict, /* op_array_handler_func_t */ | 47 | sp_op_array_handler, // zend_global_strict, /* op_array_handler_func_t */ |
| 48 | NULL, /* statement_handler_func_t */ | 48 | NULL, /* statement_handler_func_t */ |
| 49 | NULL, /* fcall_begin_handler_func_t */ | 49 | NULL, /* fcall_begin_handler_func_t */ |
| 50 | NULL, /* fcall_end_handler_func_t */ | 50 | NULL, /* fcall_end_handler_func_t */ |
| 51 | NULL, /* op_array_ctor_func_t */ | 51 | NULL, /* op_array_ctor_func_t */ |
| 52 | NULL, /* op_array_dtor_func_t */ | 52 | NULL, /* op_array_dtor_func_t */ |
| 53 | STANDARD_ZEND_EXTENSION_PROPERTIES}; | 53 | STANDARD_ZEND_EXTENSION_PROPERTIES}; |
| 54 | 54 | ||
| 55 | PHP_GINIT_FUNCTION(snuffleupagus) { | 55 | PHP_GINIT_FUNCTION(snuffleupagus) { |
| 56 | #define SP_INIT(F) F = pecalloc(sizeof(*F), 1, 1); | 56 | #define SP_INIT(F) F = pecalloc(sizeof(*F), 1, 1); |
| 57 | #define SP_INIT_HT(F) \ | 57 | #define SP_INIT_HT(F) \ |
| 58 | F = pemalloc(sizeof(*F), 1); \ | 58 | F = pemalloc(sizeof(*F), 1); \ |
| 59 | zend_hash_init(F, 10, NULL, NULL, 1); | 59 | zend_hash_init(F, 10, NULL, NULL, 1); |
| 60 | 60 | ||
| 61 | SP_INIT_HT(snuffleupagus_globals->disabled_functions_hook); | 61 | SP_INIT_HT(snuffleupagus_globals->disabled_functions_hook); |
| 62 | SP_INIT_HT(snuffleupagus_globals->sp_internal_functions_hook); | 62 | SP_INIT_HT(snuffleupagus_globals->sp_internal_functions_hook); |
| @@ -74,10 +74,14 @@ PHP_GINIT_FUNCTION(snuffleupagus) { | |||
| 74 | SP_INIT(snuffleupagus_globals->config.config_cookie); | 74 | SP_INIT(snuffleupagus_globals->config.config_cookie); |
| 75 | SP_INIT(snuffleupagus_globals->config.config_disabled_constructs); | 75 | SP_INIT(snuffleupagus_globals->config.config_disabled_constructs); |
| 76 | 76 | ||
| 77 | snuffleupagus_globals->config.config_disabled_constructs->construct_include = sp_list_new(); | 77 | snuffleupagus_globals->config.config_disabled_constructs->construct_include = |
| 78 | snuffleupagus_globals->config.config_disabled_constructs->construct_eval = sp_list_new(); | 78 | sp_list_new(); |
| 79 | snuffleupagus_globals->config.config_disabled_functions->disabled_functions = sp_list_new(); | 79 | snuffleupagus_globals->config.config_disabled_constructs->construct_eval = |
| 80 | snuffleupagus_globals->config.config_disabled_functions_ret->disabled_functions = sp_list_new(); | 80 | sp_list_new(); |
| 81 | snuffleupagus_globals->config.config_disabled_functions->disabled_functions = | ||
| 82 | sp_list_new(); | ||
| 83 | snuffleupagus_globals->config.config_disabled_functions_ret | ||
| 84 | ->disabled_functions = sp_list_new(); | ||
| 81 | snuffleupagus_globals->config.config_cookie->cookies = sp_list_new(); | 85 | snuffleupagus_globals->config.config_cookie->cookies = sp_list_new(); |
| 82 | 86 | ||
| 83 | #undef SP_INIT | 87 | #undef SP_INIT |
| @@ -91,7 +95,7 @@ PHP_MINIT_FUNCTION(snuffleupagus) { | |||
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | 97 | PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { |
| 94 | #define FREE_HT(F) \ | 98 | #define FREE_HT(F) \ |
| 95 | zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ | 99 | zend_hash_destroy(SNUFFLEUPAGUS_G(F)); \ |
| 96 | pefree(SNUFFLEUPAGUS_G(F), 1); | 100 | pefree(SNUFFLEUPAGUS_G(F), 1); |
| 97 | 101 | ||
| @@ -108,12 +112,12 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | |||
| 108 | pefree(SNUFFLEUPAGUS_G(config.config_disable_xxe), 1); | 112 | pefree(SNUFFLEUPAGUS_G(config.config_disable_xxe), 1); |
| 109 | pefree(SNUFFLEUPAGUS_G(config.config_upload_validation), 1); | 113 | pefree(SNUFFLEUPAGUS_G(config.config_upload_validation), 1); |
| 110 | 114 | ||
| 111 | #define FREE_LST_DISABLE(L) \ | 115 | #define FREE_LST_DISABLE(L) \ |
| 112 | do { \ | 116 | do { \ |
| 113 | sp_list_node* _n = SNUFFLEUPAGUS_G(L); \ | 117 | sp_list_node *_n = SNUFFLEUPAGUS_G(L); \ |
| 114 | sp_disabled_function_list_free(_n); \ | 118 | sp_disabled_function_list_free(_n); \ |
| 115 | sp_list_free(_n); \ | 119 | sp_list_free(_n); \ |
| 116 | } while(0) | 120 | } while (0) |
| 117 | 121 | ||
| 118 | FREE_LST_DISABLE(config.config_disabled_functions->disabled_functions); | 122 | FREE_LST_DISABLE(config.config_disabled_functions->disabled_functions); |
| 119 | FREE_LST_DISABLE(config.config_disabled_functions_ret->disabled_functions); | 123 | FREE_LST_DISABLE(config.config_disabled_functions_ret->disabled_functions); |
| @@ -140,7 +144,7 @@ PHP_RINIT_FUNCTION(snuffleupagus) { | |||
| 140 | if (NULL != SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { | 144 | if (NULL != SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key) { |
| 141 | if (NULL != SNUFFLEUPAGUS_G(config).config_cookie->cookies) { | 145 | if (NULL != SNUFFLEUPAGUS_G(config).config_cookie->cookies) { |
| 142 | zend_hash_apply_with_arguments( | 146 | zend_hash_apply_with_arguments( |
| 143 | Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]), decrypt_cookie, 0); | 147 | Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]), decrypt_cookie, 0); |
| 144 | } | 148 | } |
| 145 | } | 149 | } |
| 146 | return SUCCESS; | 150 | return SUCCESS; |
| @@ -152,8 +156,9 @@ PHP_MINFO_FUNCTION(snuffleupagus) { | |||
| 152 | php_info_print_table_start(); | 156 | php_info_print_table_start(); |
| 153 | php_info_print_table_row(2, "snuffleupagus support", "enabled"); | 157 | php_info_print_table_row(2, "snuffleupagus support", "enabled"); |
| 154 | php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION); | 158 | php_info_print_table_row(2, "Version", PHP_SNUFFLEUPAGUS_VERSION); |
| 155 | php_info_print_table_row(2, "Valid config", | 159 | php_info_print_table_row( |
| 156 | (SNUFFLEUPAGUS_G(is_config_valid) == true)?"yes":"no"); | 160 | 2, "Valid config", |
| 161 | (SNUFFLEUPAGUS_G(is_config_valid) == true) ? "yes" : "no"); | ||
| 157 | php_info_print_table_end(); | 162 | php_info_print_table_end(); |
| 158 | DISPLAY_INI_ENTRIES(); | 163 | DISPLAY_INI_ENTRIES(); |
| 159 | } | 164 | } |
| @@ -169,7 +174,7 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 169 | 174 | ||
| 170 | config_file = strtok(new_value->val, ","); | 175 | config_file = strtok(new_value->val, ","); |
| 171 | if (sp_parse_config(config_file) != SUCCESS) { | 176 | if (sp_parse_config(config_file) != SUCCESS) { |
| 172 | SNUFFLEUPAGUS_G(is_config_valid) = false; | 177 | SNUFFLEUPAGUS_G(is_config_valid) = false; |
| 173 | return FAILURE; | 178 | return FAILURE; |
| 174 | } | 179 | } |
| 175 | while ((config_file = strtok(NULL, ","))) { | 180 | while ((config_file = strtok(NULL, ","))) { |
| @@ -214,21 +219,21 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 214 | 219 | ||
| 215 | const zend_function_entry snuffleupagus_functions[] = {PHP_FE_END}; | 220 | const zend_function_entry snuffleupagus_functions[] = {PHP_FE_END}; |
| 216 | 221 | ||
| 217 | zend_module_entry snuffleupagus_module_entry = | 222 | zend_module_entry snuffleupagus_module_entry = { |
| 218 | {STANDARD_MODULE_HEADER, | 223 | STANDARD_MODULE_HEADER, |
| 219 | PHP_SNUFFLEUPAGUS_EXTNAME, | 224 | PHP_SNUFFLEUPAGUS_EXTNAME, |
| 220 | snuffleupagus_functions, | 225 | snuffleupagus_functions, |
| 221 | PHP_MINIT(snuffleupagus), | 226 | PHP_MINIT(snuffleupagus), |
| 222 | PHP_MSHUTDOWN(snuffleupagus), | 227 | PHP_MSHUTDOWN(snuffleupagus), |
| 223 | PHP_RINIT(snuffleupagus), | 228 | PHP_RINIT(snuffleupagus), |
| 224 | PHP_RSHUTDOWN(snuffleupagus), | 229 | PHP_RSHUTDOWN(snuffleupagus), |
| 225 | PHP_MINFO(snuffleupagus), | 230 | PHP_MINFO(snuffleupagus), |
| 226 | PHP_SNUFFLEUPAGUS_VERSION, | 231 | PHP_SNUFFLEUPAGUS_VERSION, |
| 227 | PHP_MODULE_GLOBALS(snuffleupagus), | 232 | PHP_MODULE_GLOBALS(snuffleupagus), |
| 228 | PHP_GINIT(snuffleupagus), | 233 | PHP_GINIT(snuffleupagus), |
| 229 | NULL, | 234 | NULL, |
| 230 | NULL, | 235 | NULL, |
| 231 | STANDARD_MODULE_PROPERTIES_EX}; | 236 | STANDARD_MODULE_PROPERTIES_EX}; |
| 232 | 237 | ||
| 233 | #ifdef COMPILE_DL_SNUFFLEUPAGUS | 238 | #ifdef COMPILE_DL_SNUFFLEUPAGUS |
| 234 | #ifdef ZTS | 239 | #ifdef ZTS |
diff --git a/src/sp_config.c b/src/sp_config.c index f1c7b65..aeadd9d 100644 --- a/src/sp_config.c +++ b/src/sp_config.c | |||
| @@ -35,7 +35,8 @@ static int parse_line(char *line) { | |||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | if (strncmp(ptr, SP_TOKEN_BASE, strlen(SP_TOKEN_BASE))) { | 37 | if (strncmp(ptr, SP_TOKEN_BASE, strlen(SP_TOKEN_BASE))) { |
| 38 | sp_log_err("config", "Invalid configuration prefix for '%s' on line %zu.", line, sp_line_no); | 38 | sp_log_err("config", "Invalid configuration prefix for '%s' on line %zu.", |
| 39 | line, sp_line_no); | ||
| 39 | return -1; | 40 | return -1; |
| 40 | } | 41 | } |
| 41 | ptr += strlen(SP_TOKEN_BASE); | 42 | ptr += strlen(SP_TOKEN_BASE); |
| @@ -45,7 +46,8 @@ static int parse_line(char *line) { | |||
| 45 | return sp_func[i].func(ptr + strlen(sp_func[i].token)); | 46 | return sp_func[i].func(ptr + strlen(sp_func[i].token)); |
| 46 | } | 47 | } |
| 47 | } | 48 | } |
| 48 | sp_log_err("config", "Invalid configuration section '%s' on line %zu.", line, sp_line_no); | 49 | sp_log_err("config", "Invalid configuration section '%s' on line %zu.", line, |
| 50 | sp_line_no); | ||
| 49 | return -1; | 51 | return -1; |
| 50 | } | 52 | } |
| 51 | 53 | ||
| @@ -60,32 +62,35 @@ int parse_php_type(char *restrict line, char *restrict keyword, void *retval) { | |||
| 60 | char *value = get_param(&consumed, line, SP_TYPE_STR, keyword); | 62 | char *value = get_param(&consumed, line, SP_TYPE_STR, keyword); |
| 61 | if (value) { | 63 | if (value) { |
| 62 | if (0 == strcasecmp("undef", value)) { | 64 | if (0 == strcasecmp("undef", value)) { |
| 63 | *(sp_php_type*)retval = SP_PHP_TYPE_UNDEF; | 65 | *(sp_php_type *)retval = SP_PHP_TYPE_UNDEF; |
| 64 | } else if (0 == strcasecmp("null", value)) { | 66 | } else if (0 == strcasecmp("null", value)) { |
| 65 | *(sp_php_type*)retval = SP_PHP_TYPE_NULL; | 67 | *(sp_php_type *)retval = SP_PHP_TYPE_NULL; |
| 66 | } else if (0 == strcasecmp("true", value)) { | 68 | } else if (0 == strcasecmp("true", value)) { |
| 67 | *(sp_php_type*)retval = SP_PHP_TYPE_TRUE; | 69 | *(sp_php_type *)retval = SP_PHP_TYPE_TRUE; |
| 68 | } else if (0 == strcasecmp("false", value)) { | 70 | } else if (0 == strcasecmp("false", value)) { |
| 69 | *(sp_php_type*)retval = SP_PHP_TYPE_FALSE; | 71 | *(sp_php_type *)retval = SP_PHP_TYPE_FALSE; |
| 70 | } else if (0 == strcasecmp("long", value)) { | 72 | } else if (0 == strcasecmp("long", value)) { |
| 71 | *(sp_php_type*)retval = SP_PHP_TYPE_LONG; | 73 | *(sp_php_type *)retval = SP_PHP_TYPE_LONG; |
| 72 | } else if (0 == strcasecmp("double", value)) { | 74 | } else if (0 == strcasecmp("double", value)) { |
| 73 | *(sp_php_type*)retval = SP_PHP_TYPE_DOUBLE; | 75 | *(sp_php_type *)retval = SP_PHP_TYPE_DOUBLE; |
| 74 | } else if (0 == strcasecmp("string", value)) { | 76 | } else if (0 == strcasecmp("string", value)) { |
| 75 | *(sp_php_type*)retval = SP_PHP_TYPE_STRING; | 77 | *(sp_php_type *)retval = SP_PHP_TYPE_STRING; |
| 76 | } else if (0 == strcasecmp("array", value)) { | 78 | } else if (0 == strcasecmp("array", value)) { |
| 77 | *(sp_php_type*)retval = SP_PHP_TYPE_ARRAY; | 79 | *(sp_php_type *)retval = SP_PHP_TYPE_ARRAY; |
| 78 | } else if (0 == strcasecmp("object", value)) { | 80 | } else if (0 == strcasecmp("object", value)) { |
| 79 | *(sp_php_type*)retval = SP_PHP_TYPE_OBJECT; | 81 | *(sp_php_type *)retval = SP_PHP_TYPE_OBJECT; |
| 80 | } else if (0 == strcasecmp("resource", value)) { | 82 | } else if (0 == strcasecmp("resource", value)) { |
| 81 | *(sp_php_type*)retval = SP_PHP_TYPE_RESOURCE; | 83 | *(sp_php_type *)retval = SP_PHP_TYPE_RESOURCE; |
| 82 | } else if (0 == strcasecmp("reference", value)) { | 84 | } else if (0 == strcasecmp("reference", value)) { |
| 83 | *(sp_php_type*)retval = SP_PHP_TYPE_REFERENCE; | 85 | *(sp_php_type *)retval = SP_PHP_TYPE_REFERENCE; |
| 84 | } else { | 86 | } else { |
| 85 | pefree(value, 1); | 87 | pefree(value, 1); |
| 86 | sp_log_err("error", "%s) is expecting a valid php type ('false', 'true'," | 88 | sp_log_err("error", |
| 87 | " 'array'. 'object', 'long', 'double', 'null', 'resource', 'reference'," | 89 | "%s) is expecting a valid php type ('false', 'true'," |
| 88 | " 'undef') on line %zu.", keyword, sp_line_no); | 90 | " 'array'. 'object', 'long', 'double', 'null', 'resource', " |
| 91 | "'reference'," | ||
| 92 | " 'undef') on line %zu.", | ||
| 93 | keyword, sp_line_no); | ||
| 89 | return -1; | 94 | return -1; |
| 90 | } | 95 | } |
| 91 | pefree(value, 1); | 96 | pefree(value, 1); |
| @@ -119,7 +124,8 @@ int parse_cidr(char *restrict line, char *restrict keyword, void *retval) { | |||
| 119 | *(sp_cidr **)retval = cidr; | 124 | *(sp_cidr **)retval = cidr; |
| 120 | return consumed; | 125 | return consumed; |
| 121 | } else { | 126 | } else { |
| 122 | sp_log_err("config", "%s doesn't contain a valid cidr on line %zu.", line, sp_line_no); | 127 | sp_log_err("config", "%s doesn't contain a valid cidr on line %zu.", line, |
| 128 | sp_line_no); | ||
| 123 | return -1; | 129 | return -1; |
| 124 | } | 130 | } |
| 125 | } | 131 | } |
| @@ -135,9 +141,10 @@ int parse_regexp(char *restrict line, char *restrict keyword, void *retval) { | |||
| 135 | const char *pcre_error; | 141 | const char *pcre_error; |
| 136 | int pcre_error_offset; | 142 | int pcre_error_offset; |
| 137 | pcre *compiled_re = sp_pcre_compile(value, PCRE_CASELESS, &pcre_error, | 143 | pcre *compiled_re = sp_pcre_compile(value, PCRE_CASELESS, &pcre_error, |
| 138 | &pcre_error_offset, NULL); | 144 | &pcre_error_offset, NULL); |
| 139 | if (NULL == compiled_re) { | 145 | if (NULL == compiled_re) { |
| 140 | sp_log_err("config", "Failed to compile '%s': %s on line %zu.", value, pcre_error, sp_line_no); | 146 | sp_log_err("config", "Failed to compile '%s': %s on line %zu.", value, |
| 147 | pcre_error, sp_line_no); | ||
| 141 | } else { | 148 | } else { |
| 142 | *(pcre **)retval = compiled_re; | 149 | *(pcre **)retval = compiled_re; |
| 143 | return consumed; | 150 | return consumed; |
| @@ -147,7 +154,8 @@ int parse_regexp(char *restrict line, char *restrict keyword, void *retval) { | |||
| 147 | if (NULL != closing_paren) { | 154 | if (NULL != closing_paren) { |
| 148 | closing_paren[0] = '\0'; | 155 | closing_paren[0] = '\0'; |
| 149 | } | 156 | } |
| 150 | sp_log_err("config", "'%s)' is expecting a valid regexp, and not '%s' on line %zu.", | 157 | sp_log_err("config", |
| 158 | "'%s)' is expecting a valid regexp, and not '%s' on line %zu.", | ||
| 151 | keyword, line, sp_line_no); | 159 | keyword, line, sp_line_no); |
| 152 | return -1; | 160 | return -1; |
| 153 | } | 161 | } |
| @@ -183,12 +191,11 @@ int sp_parse_config(const char *conf_file) { | |||
| 183 | return SUCCESS; | 191 | return SUCCESS; |
| 184 | } | 192 | } |
| 185 | 193 | ||
| 186 | void sp_disabled_function_list_free(sp_list_node* list) { | 194 | void sp_disabled_function_list_free(sp_list_node *list) { |
| 187 | sp_list_node* cursor = list; | 195 | sp_list_node *cursor = list; |
| 188 | while(cursor) { | 196 | while (cursor) { |
| 189 | sp_disabled_function* df = cursor->data; | 197 | sp_disabled_function *df = cursor->data; |
| 190 | if (df && df->functions_list) | 198 | if (df && df->functions_list) sp_list_free(df->functions_list); |
| 191 | sp_list_free(df->functions_list); | ||
| 192 | if (df) { | 199 | if (df) { |
| 193 | sp_tree_free(df->param); | 200 | sp_tree_free(df->param); |
| 194 | sp_tree_free(df->var); | 201 | sp_tree_free(df->var); |
diff --git a/src/sp_config.h b/src/sp_config.h index aca9ff6..2417cf9 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -43,8 +43,8 @@ typedef struct { | |||
| 43 | } sp_config_global; | 43 | } sp_config_global; |
| 44 | 44 | ||
| 45 | typedef struct { | 45 | typedef struct { |
| 46 | bool enable; | 46 | bool enable; |
| 47 | bool simulation; | 47 | bool simulation; |
| 48 | } sp_config_readonly_exec; | 48 | } sp_config_readonly_exec; |
| 49 | 49 | ||
| 50 | typedef struct { bool enable; } sp_config_global_strict; | 50 | typedef struct { bool enable; } sp_config_global_strict; |
| @@ -56,7 +56,7 @@ typedef struct { bool enable; } sp_config_auto_cookie_secure; | |||
| 56 | typedef struct { bool enable; } sp_config_disable_xxe; | 56 | typedef struct { bool enable; } sp_config_disable_xxe; |
| 57 | 57 | ||
| 58 | typedef struct { | 58 | typedef struct { |
| 59 | enum samesite_type {strict=1, lax=2} samesite; | 59 | enum samesite_type { strict = 1, lax = 2 } samesite; |
| 60 | bool encrypt; | 60 | bool encrypt; |
| 61 | char *name; | 61 | char *name; |
| 62 | pcre *name_r; | 62 | pcre *name_r; |
| @@ -116,11 +116,12 @@ typedef struct { | |||
| 116 | } sp_config_disabled_functions; | 116 | } sp_config_disabled_functions; |
| 117 | 117 | ||
| 118 | typedef struct { | 118 | typedef struct { |
| 119 | sp_list_node *cookies; //list of sp_cookie for regexp/names | 119 | sp_list_node *cookies; // list of sp_cookie for regexp/names |
| 120 | } sp_config_cookie; | 120 | } sp_config_cookie; |
| 121 | 121 | ||
| 122 | typedef struct { | 122 | typedef struct { |
| 123 | sp_list_node *construct_include; // list of rules for `(include|require)_(once)?` | 123 | sp_list_node |
| 124 | *construct_include; // list of rules for `(include|require)_(once)?` | ||
| 124 | sp_list_node *construct_eval; | 125 | sp_list_node *construct_eval; |
| 125 | sp_list_node *construct_echo; | 126 | sp_list_node *construct_echo; |
| 126 | } sp_config_disabled_constructs; | 127 | } sp_config_disabled_constructs; |
| @@ -231,6 +232,6 @@ int parse_cidr(char *restrict, char *restrict, void *); | |||
| 231 | int parse_php_type(char *restrict, char *restrict, void *); | 232 | int parse_php_type(char *restrict, char *restrict, void *); |
| 232 | 233 | ||
| 233 | // cleanup | 234 | // cleanup |
| 234 | void sp_disabled_function_list_free(sp_list_node*); | 235 | void sp_disabled_function_list_free(sp_list_node *); |
| 235 | 236 | ||
| 236 | #endif /* SP_CONFIG_H */ | 237 | #endif /* SP_CONFIG_H */ |
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index b3e71fe..998b692 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c | |||
| @@ -108,12 +108,12 @@ int parse_cookie(char *line) { | |||
| 108 | sp_cookie *cookie = pecalloc(sizeof(sp_cookie), 1, 1); | 108 | sp_cookie *cookie = pecalloc(sizeof(sp_cookie), 1, 1); |
| 109 | 109 | ||
| 110 | sp_config_functions sp_config_funcs_cookie_encryption[] = { | 110 | sp_config_functions sp_config_funcs_cookie_encryption[] = { |
| 111 | {parse_str, SP_TOKEN_NAME, &(cookie->name)}, | 111 | {parse_str, SP_TOKEN_NAME, &(cookie->name)}, |
| 112 | {parse_regexp, SP_TOKEN_NAME_REGEXP, &(cookie->name_r)}, | 112 | {parse_regexp, SP_TOKEN_NAME_REGEXP, &(cookie->name_r)}, |
| 113 | {parse_str, SP_TOKEN_SAMESITE, &samesite}, | 113 | {parse_str, SP_TOKEN_SAMESITE, &samesite}, |
| 114 | {parse_empty, SP_TOKEN_ENCRYPT, &cookie->encrypt}, | 114 | {parse_empty, SP_TOKEN_ENCRYPT, &cookie->encrypt}, |
| 115 | {parse_empty, SP_TOKEN_SIMULATION, &cookie->simulation}, | 115 | {parse_empty, SP_TOKEN_SIMULATION, &cookie->simulation}, |
| 116 | {0}}; | 116 | {0}}; |
| 117 | 117 | ||
| 118 | ret = parse_keywords(sp_config_funcs_cookie_encryption, line); | 118 | ret = parse_keywords(sp_config_funcs_cookie_encryption, line); |
| 119 | if (0 != ret) { | 119 | if (0 != ret) { |
| @@ -122,18 +122,21 @@ int parse_cookie(char *line) { | |||
| 122 | 122 | ||
| 123 | if (cookie->encrypt) { | 123 | if (cookie->encrypt) { |
| 124 | if (0 == (SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)) { | 124 | if (0 == (SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)) { |
| 125 | sp_log_err("config", | 125 | sp_log_err( |
| 126 | "You're trying to use the cookie encryption feature" | 126 | "config", |
| 127 | "on line %zu without having set the `.cookie_env_var` option in" | 127 | "You're trying to use the cookie encryption feature" |
| 128 | "`sp.global`: please set it first.", | 128 | "on line %zu without having set the `.cookie_env_var` option in" |
| 129 | "`sp.global`: please set it first.", | ||
| 129 | sp_line_no); | 130 | sp_line_no); |
| 130 | return -1; | 131 | return -1; |
| 131 | } else if (0 == (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) { | 132 | } else if (0 == |
| 132 | sp_log_err("config", | 133 | (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) { |
| 133 | "You're trying to use the cookie encryption feature" | 134 | sp_log_err( |
| 134 | "on line %zu without having set the `.encryption_key` option in" | 135 | "config", |
| 135 | "`sp.global`: please set it first.", | 136 | "You're trying to use the cookie encryption feature" |
| 136 | sp_line_no); | 137 | "on line %zu without having set the `.encryption_key` option in" |
| 138 | "`sp.global`: please set it first.", | ||
| 139 | sp_line_no); | ||
| 137 | return -1; | 140 | return -1; |
| 138 | } | 141 | } |
| 139 | } else if (!samesite) { | 142 | } else if (!samesite) { |
| @@ -163,16 +166,16 @@ int parse_cookie(char *line) { | |||
| 163 | } else if (0 == strcasecmp(samesite, SP_TOKEN_SAMESITE_STRICT)) { | 166 | } else if (0 == strcasecmp(samesite, SP_TOKEN_SAMESITE_STRICT)) { |
| 164 | cookie->samesite = strict; | 167 | cookie->samesite = strict; |
| 165 | } else { | 168 | } else { |
| 166 | sp_log_err("config", | 169 | sp_log_err( |
| 167 | "%s is an invalid value to samesite (expected %s or %s) on line " | 170 | "config", |
| 168 | "%zu.", | 171 | "%s is an invalid value to samesite (expected %s or %s) on line " |
| 169 | samesite, SP_TOKEN_SAMESITE_LAX, SP_TOKEN_SAMESITE_STRICT, | 172 | "%zu.", |
| 170 | sp_line_no); | 173 | samesite, SP_TOKEN_SAMESITE_LAX, SP_TOKEN_SAMESITE_STRICT, |
| 174 | sp_line_no); | ||
| 171 | return -1; | 175 | return -1; |
| 172 | } | 176 | } |
| 173 | } | 177 | } |
| 174 | sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, | 178 | sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, cookie); |
| 175 | cookie); | ||
| 176 | return SUCCESS; | 179 | return SUCCESS; |
| 177 | } | 180 | } |
| 178 | 181 | ||
| @@ -235,8 +238,8 @@ int parse_disabled_functions(char *line) { | |||
| 235 | MUTUALLY_EXCLUSIVE(df->key, df->r_key, "r_key", "key"); | 238 | MUTUALLY_EXCLUSIVE(df->key, df->r_key, "r_key", "key"); |
| 236 | #undef MUTUALLY_EXCLUSIVE | 239 | #undef MUTUALLY_EXCLUSIVE |
| 237 | 240 | ||
| 238 | if (1 < ((df->r_param ? 1 : 0) + (param ? 1 : 0) + | 241 | if (1 < |
| 239 | ((-1 != df->pos) ? 1 : 0))) { | 242 | ((df->r_param ? 1 : 0) + (param ? 1 : 0) + ((-1 != df->pos) ? 1 : 0))) { |
| 240 | sp_log_err( | 243 | sp_log_err( |
| 241 | "config", | 244 | "config", |
| 242 | "Invalid configuration line: 'sp.disabled_functions%s':" | 245 | "Invalid configuration line: 'sp.disabled_functions%s':" |
| @@ -306,8 +309,8 @@ int parse_disabled_functions(char *line) { | |||
| 306 | if (param) { | 309 | if (param) { |
| 307 | df->param = parse_var(param); | 310 | df->param = parse_var(param); |
| 308 | if (!df->param) { | 311 | if (!df->param) { |
| 309 | sp_log_err("config", "Invalid value '%s' for `param` on line %zu.", | 312 | sp_log_err("config", "Invalid value '%s' for `param` on line %zu.", param, |
| 310 | param, sp_line_no); | 313 | sp_line_no); |
| 311 | return -1; | 314 | return -1; |
| 312 | } | 315 | } |
| 313 | } | 316 | } |
| @@ -316,13 +319,12 @@ int parse_disabled_functions(char *line) { | |||
| 316 | if (*var) { | 319 | if (*var) { |
| 317 | df->var = parse_var(var); | 320 | df->var = parse_var(var); |
| 318 | if (!df->var) { | 321 | if (!df->var) { |
| 319 | sp_log_err("config", "Invalid value '%s' for `var` on line %zu.", | 322 | sp_log_err("config", "Invalid value '%s' for `var` on line %zu.", var, |
| 320 | var, sp_line_no); | 323 | sp_line_no); |
| 321 | return -1; | 324 | return -1; |
| 322 | } | 325 | } |
| 323 | } else { | 326 | } else { |
| 324 | sp_log_err("config", "Empty value in `var` on line %zu.", | 327 | sp_log_err("config", "Empty value in `var` on line %zu.", sp_line_no); |
| 325 | sp_line_no); | ||
| 326 | return -1; | 328 | return -1; |
| 327 | } | 329 | } |
| 328 | } | 330 | } |
diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h index fdea1c5..8286997 100644 --- a/src/sp_config_keywords.h +++ b/src/sp_config_keywords.h | |||
| @@ -6,11 +6,11 @@ int parse_random(char *line); | |||
| 6 | int parse_disable_xxe(char *line); | 6 | int parse_disable_xxe(char *line); |
| 7 | int parse_auto_cookie_secure(char *line); | 7 | int parse_auto_cookie_secure(char *line); |
| 8 | int parse_global_strict(char *line); | 8 | int parse_global_strict(char *line); |
| 9 | int parse_global(char *line) ; | 9 | int parse_global(char *line); |
| 10 | int parse_cookie(char *line); | 10 | int parse_cookie(char *line); |
| 11 | int parse_unserialize(char *line) ; | 11 | int parse_unserialize(char *line); |
| 12 | int parse_readonly_exec(char *line); | 12 | int parse_readonly_exec(char *line); |
| 13 | int parse_disabled_functions(char *line) ; | 13 | int parse_disabled_functions(char *line); |
| 14 | int parse_upload_validation(char *line); | 14 | int parse_upload_validation(char *line); |
| 15 | 15 | ||
| 16 | #endif // __SP_CONFIG_KEYWORDS_H | 16 | #endif // __SP_CONFIG_KEYWORDS_H |
diff --git a/src/sp_config_utils.c b/src/sp_config_utils.c index bf558d4..20d4d79 100644 --- a/src/sp_config_utils.c +++ b/src/sp_config_utils.c | |||
| @@ -26,14 +26,14 @@ int parse_keywords(sp_config_functions *funcs, char *line) { | |||
| 26 | 26 | ||
| 27 | if (*line) { | 27 | if (*line) { |
| 28 | sp_log_err("config", "Trailing chars '%s' at the end of '%s' on line %zu.", | 28 | sp_log_err("config", "Trailing chars '%s' at the end of '%s' on line %zu.", |
| 29 | line, original_line, sp_line_no); | 29 | line, original_line, sp_line_no); |
| 30 | return -1; | 30 | return -1; |
| 31 | } | 31 | } |
| 32 | return 0; | 32 | return 0; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | char *get_param(size_t *consumed, char *restrict line, sp_type type, | 35 | char *get_param(size_t *consumed, char *restrict line, sp_type type, |
| 36 | const char *restrict keyword) { | 36 | const char *restrict keyword) { |
| 37 | enum { IN_ESCAPE, NONE } state = NONE; | 37 | enum { IN_ESCAPE, NONE } state = NONE; |
| 38 | char *original_line = line; | 38 | char *original_line = line; |
| 39 | size_t j = 0; | 39 | size_t j = 0; |
| @@ -86,10 +86,12 @@ char *get_param(size_t *consumed, char *restrict line, sp_type type, | |||
| 86 | } | 86 | } |
| 87 | err: | 87 | err: |
| 88 | if (0 == j) { | 88 | if (0 == j) { |
| 89 | sp_log_err("error", "A valid string as parameter is expected on line %zu.", sp_line_no); | 89 | sp_log_err("error", "A valid string as parameter is expected on line %zu.", |
| 90 | sp_line_no); | ||
| 90 | } else { | 91 | } else { |
| 91 | sp_log_err("error", | 92 | sp_log_err("error", |
| 92 | "There is an issue with the parsing of '%s': it doesn't look like a valid string on line %zu.", | 93 | "There is an issue with the parsing of '%s': it doesn't look " |
| 94 | "like a valid string on line %zu.", | ||
| 93 | original_line ? original_line : "NULL", sp_line_no); | 95 | original_line ? original_line : "NULL", sp_line_no); |
| 94 | } | 96 | } |
| 95 | line = NULL; | 97 | line = NULL; |
| @@ -104,8 +106,8 @@ zend_always_inline sp_list_node *parse_functions_list(char *value) { | |||
| 104 | } | 106 | } |
| 105 | 107 | ||
| 106 | sp_list_node *list = sp_list_new(); | 108 | sp_list_node *list = sp_list_new(); |
| 107 | char* tmp = strdup(value); | 109 | char *tmp = strdup(value); |
| 108 | char* function_name; | 110 | char *function_name; |
| 109 | char *next_token = tmp; | 111 | char *next_token = tmp; |
| 110 | while ((function_name = strtok_r(NULL, sep, &next_token))) { | 112 | while ((function_name = strtok_r(NULL, sep, &next_token))) { |
| 111 | sp_list_prepend(list, strdup(function_name)); | 113 | sp_list_prepend(list, strdup(function_name)); |
diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c index 4e9818f..6abc20a 100644 --- a/src/sp_cookie_encryption.c +++ b/src/sp_cookie_encryption.c | |||
| @@ -10,12 +10,12 @@ static inline void generate_key(unsigned char *key) { | |||
| 10 | PHP_SHA256_CTX ctx; | 10 | PHP_SHA256_CTX ctx; |
| 11 | const char *user_agent = getenv("HTTP_USER_AGENT"); | 11 | const char *user_agent = getenv("HTTP_USER_AGENT"); |
| 12 | const char *env_var = | 12 | const char *env_var = |
| 13 | getenv(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var); | 13 | getenv(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var); |
| 14 | const char *encryption_key = | 14 | const char *encryption_key = |
| 15 | SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key; | 15 | SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key; |
| 16 | 16 | ||
| 17 | assert(32 == crypto_secretbox_KEYBYTES); // 32 is the size of a SHA256. | 17 | assert(32 == crypto_secretbox_KEYBYTES); // 32 is the size of a SHA256. |
| 18 | assert(encryption_key); // Encryption key can't be NULL | 18 | assert(encryption_key); // Encryption key can't be NULL |
| 19 | 19 | ||
| 20 | PHP_SHA256Init(&ctx); | 20 | PHP_SHA256Init(&ctx); |
| 21 | 21 | ||
| @@ -24,11 +24,12 @@ static inline void generate_key(unsigned char *key) { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | if (env_var) { | 26 | if (env_var) { |
| 27 | PHP_SHA256Update(&ctx, (unsigned char*)env_var, strlen(env_var)); | 27 | PHP_SHA256Update(&ctx, (unsigned char *)env_var, strlen(env_var)); |
| 28 | } else { | 28 | } else { |
| 29 | sp_log_err("cookie_encryption", "The environment variable '%s'" | 29 | sp_log_err("cookie_encryption", |
| 30 | "is empty, cookies are weakly encrypted.", | 30 | "The environment variable '%s'" |
| 31 | SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var); | 31 | "is empty, cookies are weakly encrypted.", |
| 32 | SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var); | ||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | if (encryption_key) { | 35 | if (encryption_key) { |
| @@ -41,9 +42,9 @@ static inline void generate_key(unsigned char *key) { | |||
| 41 | 42 | ||
| 42 | static inline const sp_cookie *sp_lookup_cookie_config(const char *key) { | 43 | static inline const sp_cookie *sp_lookup_cookie_config(const char *key) { |
| 43 | sp_list_node *it = SNUFFLEUPAGUS_G(config).config_cookie->cookies; | 44 | sp_list_node *it = SNUFFLEUPAGUS_G(config).config_cookie->cookies; |
| 44 | 45 | ||
| 45 | while (it) { | 46 | while (it) { |
| 46 | const sp_cookie *config = it->data; | 47 | const sp_cookie *config = it->data; |
| 47 | if (config && sp_match_value(key, config->name, config->name_r)) { | 48 | if (config && sp_match_value(key, config->name, config->name_r)) { |
| 48 | return config; | 49 | return config; |
| 49 | } | 50 | } |
| @@ -60,7 +61,7 @@ int decrypt_cookie(zval *pDest, int num_args, va_list args, | |||
| 60 | unsigned char *decrypted; | 61 | unsigned char *decrypted; |
| 61 | const sp_cookie *cookie = sp_lookup_cookie_config(ZSTR_VAL(hash_key->key)); | 62 | const sp_cookie *cookie = sp_lookup_cookie_config(ZSTR_VAL(hash_key->key)); |
| 62 | int ret = 0; | 63 | int ret = 0; |
| 63 | 64 | ||
| 64 | /* If the cookie isn't in the conf, it shouldn't be encrypted. */ | 65 | /* If the cookie isn't in the conf, it shouldn't be encrypted. */ |
| 65 | if (!cookie || !cookie->encrypt) { | 66 | if (!cookie || !cookie->encrypt) { |
| 66 | return ZEND_HASH_APPLY_KEEP; | 67 | return ZEND_HASH_APPLY_KEEP; |
| @@ -72,18 +73,20 @@ int decrypt_cookie(zval *pDest, int num_args, va_list args, | |||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | debase64 = php_base64_decode((unsigned char *)(Z_STRVAL_P(pDest)), | 75 | debase64 = php_base64_decode((unsigned char *)(Z_STRVAL_P(pDest)), |
| 75 | Z_STRLEN_P(pDest)); | 76 | Z_STRLEN_P(pDest)); |
| 76 | 77 | ||
| 77 | if (ZSTR_LEN(debase64) < | 78 | if (ZSTR_LEN(debase64) < |
| 78 | crypto_secretbox_NONCEBYTES + crypto_secretbox_ZEROBYTES) { | 79 | crypto_secretbox_NONCEBYTES + crypto_secretbox_ZEROBYTES) { |
| 79 | if (true == cookie->simulation) { | 80 | if (true == cookie->simulation) { |
| 80 | sp_log_msg("cookie_encryption", SP_LOG_SIMULATION, | 81 | sp_log_msg( |
| 82 | "cookie_encryption", SP_LOG_SIMULATION, | ||
| 81 | "Buffer underflow tentative detected in cookie encryption handling " | 83 | "Buffer underflow tentative detected in cookie encryption handling " |
| 82 | "for %s. Using the cookie 'as it' instead of decrypting it.", | 84 | "for %s. Using the cookie 'as it' instead of decrypting it.", |
| 83 | ZSTR_VAL(hash_key->key)); | 85 | ZSTR_VAL(hash_key->key)); |
| 84 | return ZEND_HASH_APPLY_KEEP; | 86 | return ZEND_HASH_APPLY_KEEP; |
| 85 | } else { | 87 | } else { |
| 86 | sp_log_msg("cookie_encryption", SP_LOG_DROP, | 88 | sp_log_msg( |
| 89 | "cookie_encryption", SP_LOG_DROP, | ||
| 87 | "Buffer underflow tentative detected in cookie encryption handling."); | 90 | "Buffer underflow tentative detected in cookie encryption handling."); |
| 88 | return ZEND_HASH_APPLY_REMOVE; | 91 | return ZEND_HASH_APPLY_REMOVE; |
| 89 | } | 92 | } |
| @@ -101,14 +104,16 @@ int decrypt_cookie(zval *pDest, int num_args, va_list args, | |||
| 101 | 104 | ||
| 102 | if (-1 == ret) { | 105 | if (-1 == ret) { |
| 103 | if (true == cookie->simulation) { | 106 | if (true == cookie->simulation) { |
| 104 | sp_log_msg("cookie_encryption", SP_LOG_SIMULATION, | 107 | sp_log_msg( |
| 105 | "Something went wrong with the decryption of %s. Using the cookie " | 108 | "cookie_encryption", SP_LOG_SIMULATION, |
| 106 | "'as it' instead of decrypting it", ZSTR_VAL(hash_key->key)); | 109 | "Something went wrong with the decryption of %s. Using the cookie " |
| 110 | "'as it' instead of decrypting it", | ||
| 111 | ZSTR_VAL(hash_key->key)); | ||
| 107 | return ZEND_HASH_APPLY_KEEP; | 112 | return ZEND_HASH_APPLY_KEEP; |
| 108 | } else { | 113 | } else { |
| 109 | sp_log_msg("cookie_encryption", SP_LOG_DROP, | 114 | sp_log_msg("cookie_encryption", SP_LOG_DROP, |
| 110 | "Something went wrong with the decryption of %s.", | 115 | "Something went wrong with the decryption of %s.", |
| 111 | ZSTR_VAL(hash_key->key)); | 116 | ZSTR_VAL(hash_key->key)); |
| 112 | return ZEND_HASH_APPLY_REMOVE; | 117 | return ZEND_HASH_APPLY_REMOVE; |
| 113 | } | 118 | } |
| 114 | } | 119 | } |
| @@ -127,7 +132,8 @@ int decrypt_cookie(zval *pDest, int num_args, va_list args, | |||
| 127 | */ | 132 | */ |
| 128 | static zend_string *encrypt_data(char *data, unsigned long long data_len) { | 133 | static zend_string *encrypt_data(char *data, unsigned long long data_len) { |
| 129 | const size_t encrypted_msg_len = crypto_secretbox_ZEROBYTES + data_len + 1; | 134 | const size_t encrypted_msg_len = crypto_secretbox_ZEROBYTES + data_len + 1; |
| 130 | const size_t emsg_and_nonce_len = encrypted_msg_len + crypto_secretbox_NONCEBYTES; | 135 | const size_t emsg_and_nonce_len = |
| 136 | encrypted_msg_len + crypto_secretbox_NONCEBYTES; | ||
| 131 | 137 | ||
| 132 | unsigned char key[crypto_secretbox_KEYBYTES] = {0}; | 138 | unsigned char key[crypto_secretbox_KEYBYTES] = {0}; |
| 133 | unsigned char nonce[crypto_secretbox_NONCEBYTES] = {0}; | 139 | unsigned char nonce[crypto_secretbox_NONCEBYTES] = {0}; |
| @@ -149,7 +155,7 @@ static zend_string *encrypt_data(char *data, unsigned long long data_len) { | |||
| 149 | } | 155 | } |
| 150 | } | 156 | } |
| 151 | nonce_d++; | 157 | nonce_d++; |
| 152 | sscanf((char*)nonce, "%ld", &nonce_d); | 158 | sscanf((char *)nonce, "%ld", &nonce_d); |
| 153 | 159 | ||
| 154 | memcpy(encrypted_data, nonce, crypto_secretbox_NONCEBYTES); | 160 | memcpy(encrypted_data, nonce, crypto_secretbox_NONCEBYTES); |
| 155 | crypto_secretbox(encrypted_data + crypto_secretbox_NONCEBYTES, | 161 | crypto_secretbox(encrypted_data + crypto_secretbox_NONCEBYTES, |
| @@ -161,15 +167,15 @@ static zend_string *encrypt_data(char *data, unsigned long long data_len) { | |||
| 161 | } | 167 | } |
| 162 | 168 | ||
| 163 | PHP_FUNCTION(sp_setcookie) { | 169 | PHP_FUNCTION(sp_setcookie) { |
| 164 | zval params[7] = { 0 }; | 170 | zval params[7] = {0}; |
| 165 | zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, *samesite = NULL; | 171 | zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, |
| 172 | *samesite = NULL; | ||
| 166 | zend_long expires = 0; | 173 | zend_long expires = 0; |
| 167 | zend_bool secure = 0, httponly = 0; | 174 | zend_bool secure = 0, httponly = 0; |
| 168 | const sp_cookie *cookie_node = NULL; | 175 | const sp_cookie *cookie_node = NULL; |
| 169 | zval func_name; | 176 | zval func_name; |
| 170 | char *cookie_samesite; | 177 | char *cookie_samesite; |
| 171 | 178 | ||
| 172 | |||
| 173 | // LCOV_EXCL_BR_START | 179 | // LCOV_EXCL_BR_START |
| 174 | ZEND_PARSE_PARAMETERS_START(1, 7) | 180 | ZEND_PARSE_PARAMETERS_START(1, 7) |
| 175 | Z_PARAM_STR(name) | 181 | Z_PARAM_STR(name) |
| @@ -197,7 +203,7 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 197 | 203 | ||
| 198 | /* lookup existing configuration for said cookie */ | 204 | /* lookup existing configuration for said cookie */ |
| 199 | cookie_node = sp_lookup_cookie_config(ZSTR_VAL(name)); | 205 | cookie_node = sp_lookup_cookie_config(ZSTR_VAL(name)); |
| 200 | 206 | ||
| 201 | /* If the cookie's value is encrypted, it won't be usable by | 207 | /* If the cookie's value is encrypted, it won't be usable by |
| 202 | * javascript anyway. | 208 | * javascript anyway. |
| 203 | */ | 209 | */ |
| @@ -233,12 +239,15 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 233 | if (!path) { | 239 | if (!path) { |
| 234 | path = zend_string_init("", 0, 0); | 240 | path = zend_string_init("", 0, 0); |
| 235 | } | 241 | } |
| 236 | cookie_samesite = (cookie_node->samesite == lax) ? SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_LAX | 242 | cookie_samesite = (cookie_node->samesite == lax) |
| 237 | : SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_STRICT; | 243 | ? SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_LAX |
| 244 | : SAMESITE_COOKIE_FORMAT SP_TOKEN_SAMESITE_STRICT; | ||
| 238 | /* Concatenating everything, as is in PHP internals */ | 245 | /* Concatenating everything, as is in PHP internals */ |
| 239 | samesite = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0); | 246 | samesite = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0); |
| 240 | samesite = zend_string_extend(samesite, ZSTR_LEN(path) + strlen(cookie_samesite) + 1, 0); | 247 | samesite = zend_string_extend( |
| 241 | memcpy(ZSTR_VAL(samesite) + ZSTR_LEN(path), cookie_samesite, strlen(cookie_samesite) + 1); | 248 | samesite, ZSTR_LEN(path) + strlen(cookie_samesite) + 1, 0); |
| 249 | memcpy(ZSTR_VAL(samesite) + ZSTR_LEN(path), cookie_samesite, | ||
| 250 | strlen(cookie_samesite) + 1); | ||
| 242 | ZVAL_STR_COPY(¶ms[3], samesite); | 251 | ZVAL_STR_COPY(¶ms[3], samesite); |
| 243 | } else if (path) { | 252 | } else if (path) { |
| 244 | ZVAL_STR_COPY(¶ms[3], path); | 253 | ZVAL_STR_COPY(¶ms[3], path); |
| @@ -250,20 +259,22 @@ PHP_FUNCTION(sp_setcookie) { | |||
| 250 | This is why were replacing our hook with the original function, calling | 259 | This is why were replacing our hook with the original function, calling |
| 251 | the function, and then re-hooking it. */ | 260 | the function, and then re-hooking it. */ |
| 252 | void (*handler)(INTERNAL_FUNCTION_PARAMETERS); | 261 | void (*handler)(INTERNAL_FUNCTION_PARAMETERS); |
| 253 | handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), "setcookie", | 262 | handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), |
| 254 | strlen("setcookie")); | 263 | "setcookie", strlen("setcookie")); |
| 255 | zend_internal_function *func = zend_hash_str_find_ptr( | 264 | zend_internal_function *func = zend_hash_str_find_ptr( |
| 256 | CG(function_table), "setcookie", strlen("setcookie")); | 265 | CG(function_table), "setcookie", strlen("setcookie")); |
| 257 | func->handler = handler; | 266 | func->handler = handler; |
| 258 | 267 | ||
| 259 | call_user_function(CG(function_table), NULL, &func_name, return_value, 7, params); | 268 | call_user_function(CG(function_table), NULL, &func_name, return_value, 7, |
| 269 | params); | ||
| 260 | 270 | ||
| 261 | func->handler = PHP_FN(sp_setcookie); | 271 | func->handler = PHP_FN(sp_setcookie); |
| 262 | RETURN_TRUE; | 272 | RETURN_TRUE; |
| 263 | } | 273 | } |
| 264 | 274 | ||
| 265 | int hook_cookies() { | 275 | int hook_cookies() { |
| 266 | HOOK_FUNCTION("setcookie", sp_internal_functions_hook, PHP_FN(sp_setcookie), false); | 276 | HOOK_FUNCTION("setcookie", sp_internal_functions_hook, PHP_FN(sp_setcookie), |
| 277 | false); | ||
| 267 | 278 | ||
| 268 | return SUCCESS; | 279 | return SUCCESS; |
| 269 | } | 280 | } |
diff --git a/src/sp_cookie_encryption.h b/src/sp_cookie_encryption.h index 889a89c..6d204bb 100644 --- a/src/sp_cookie_encryption.h +++ b/src/sp_cookie_encryption.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #define SAMESITE_COOKIE_FORMAT "; samesite=" | 14 | #define SAMESITE_COOKIE_FORMAT "; samesite=" |
| 15 | 15 | ||
| 16 | int hook_cookies(); | 16 | int hook_cookies(); |
| 17 | int decrypt_cookie(zval *pDest, int num_args, va_list args, zend_hash_key *hash_key); | 17 | int decrypt_cookie(zval *pDest, int num_args, va_list args, |
| 18 | zend_hash_key *hash_key); | ||
| 18 | 19 | ||
| 19 | #endif /* __SP_COOKIE_ENCRYPTION */ | 20 | #endif /* __SP_COOKIE_ENCRYPTION */ |
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 9736d2b..9382b09 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -64,25 +64,25 @@ end: | |||
| 64 | static bool is_local_var_matching( | 64 | static bool is_local_var_matching( |
| 65 | zend_execute_data* execute_data, | 65 | zend_execute_data* execute_data, |
| 66 | const sp_disabled_function* const config_node) { | 66 | const sp_disabled_function* const config_node) { |
| 67 | zval *var_value; | 67 | zval* var_value; |
| 68 | 68 | ||
| 69 | var_value = get_value(execute_data, config_node->var, false); | 69 | var_value = get_value(execute_data, config_node->var, false); |
| 70 | if (var_value) { | 70 | if (var_value) { |
| 71 | char *var_value_str = sp_convert_to_string(var_value); | 71 | char* var_value_str = sp_convert_to_string(var_value); |
| 72 | if (Z_TYPE_P(var_value) == IS_ARRAY) { | 72 | if (Z_TYPE_P(var_value) == IS_ARRAY) { |
| 73 | if (config_node->key || config_node->r_key) { | 73 | if (config_node->key || config_node->r_key) { |
| 74 | if (sp_match_array_key(var_value, config_node->key, | 74 | if (sp_match_array_key(var_value, config_node->key, |
| 75 | config_node->r_key)) { | 75 | config_node->r_key)) { |
| 76 | efree(var_value_str); | 76 | efree(var_value_str); |
| 77 | return true; | 77 | return true; |
| 78 | } | 78 | } |
| 79 | } else if (sp_match_array_value(var_value, config_node->value, | 79 | } else if (sp_match_array_value(var_value, config_node->value, |
| 80 | config_node->value_r)) { | 80 | config_node->value_r)) { |
| 81 | efree(var_value_str); | 81 | efree(var_value_str); |
| 82 | return true; | 82 | return true; |
| 83 | } | 83 | } |
| 84 | } else if (sp_match_value(var_value_str, config_node->value, | 84 | } else if (sp_match_value(var_value_str, config_node->value, |
| 85 | config_node->value_r)) { | 85 | config_node->value_r)) { |
| 86 | efree(var_value_str); | 86 | efree(var_value_str); |
| 87 | return true; | 87 | return true; |
| 88 | } | 88 | } |
| @@ -115,7 +115,7 @@ static bool is_param_matching(zend_execute_data* execute_data, | |||
| 115 | const char** arg_value_str) { | 115 | const char** arg_value_str) { |
| 116 | int nb_param = execute_data->func->common.num_args; | 116 | int nb_param = execute_data->func->common.num_args; |
| 117 | int i = 0; | 117 | int i = 0; |
| 118 | zval *arg_value; | 118 | zval* arg_value; |
| 119 | 119 | ||
| 120 | if (config_node->pos != -1) { | 120 | if (config_node->pos != -1) { |
| 121 | if (config_node->pos <= nb_param) { | 121 | if (config_node->pos <= nb_param) { |
| @@ -150,8 +150,9 @@ static bool is_param_matching(zend_execute_data* execute_data, | |||
| 150 | } else { | 150 | } else { |
| 151 | *arg_name = execute_data->func->internal_function.arg_info[i].name; | 151 | *arg_name = execute_data->func->internal_function.arg_info[i].name; |
| 152 | } | 152 | } |
| 153 | const bool pcre_matching = config_node->r_param | 153 | const bool pcre_matching = |
| 154 | && (true == is_regexp_matching(config_node->r_param, *arg_name)); | 154 | config_node->r_param && |
| 155 | (true == is_regexp_matching(config_node->r_param, *arg_name)); | ||
| 155 | 156 | ||
| 156 | /* This is the parameter name we're looking for. */ | 157 | /* This is the parameter name we're looking for. */ |
| 157 | if (true == pcre_matching || config_node->pos != -1) { | 158 | if (true == pcre_matching || config_node->pos != -1) { |
| @@ -159,23 +160,23 @@ static bool is_param_matching(zend_execute_data* execute_data, | |||
| 159 | 160 | ||
| 160 | if (config_node->param_type) { // Are we matching on the `type`? | 161 | if (config_node->param_type) { // Are we matching on the `type`? |
| 161 | if (config_node->param_type == Z_TYPE_P(arg_value)) { | 162 | if (config_node->param_type == Z_TYPE_P(arg_value)) { |
| 162 | return true; | 163 | return true; |
| 163 | } | 164 | } |
| 164 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | 165 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { |
| 165 | *arg_value_str = sp_convert_to_string(arg_value); | 166 | *arg_value_str = sp_convert_to_string(arg_value); |
| 166 | if (config_node->key || config_node->r_key) { | 167 | if (config_node->key || config_node->r_key) { |
| 167 | if (sp_match_array_key(arg_value, config_node->key, | 168 | if (sp_match_array_key(arg_value, config_node->key, |
| 168 | config_node->r_key)) { | 169 | config_node->r_key)) { |
| 169 | return true; | 170 | return true; |
| 170 | } | 171 | } |
| 171 | } else if (sp_match_array_value(arg_value, config_node->value, | 172 | } else if (sp_match_array_value(arg_value, config_node->value, |
| 172 | config_node->value_r)) { | 173 | config_node->value_r)) { |
| 173 | return true; | 174 | return true; |
| 174 | } | 175 | } |
| 175 | } else { | 176 | } else { |
| 176 | *arg_value_str = sp_convert_to_string(arg_value); | 177 | *arg_value_str = sp_convert_to_string(arg_value); |
| 177 | if (sp_match_value(*arg_value_str, config_node->value, | 178 | if (sp_match_value(*arg_value_str, config_node->value, |
| 178 | config_node->value_r)) { | 179 | config_node->value_r)) { |
| 179 | return true; | 180 | return true; |
| 180 | } | 181 | } |
| 181 | } | 182 | } |
| @@ -188,23 +189,23 @@ static bool is_param_matching(zend_execute_data* execute_data, | |||
| 188 | if (arg_value) { | 189 | if (arg_value) { |
| 189 | *arg_value_str = sp_convert_to_string(arg_value); | 190 | *arg_value_str = sp_convert_to_string(arg_value); |
| 190 | if (config_node->param_type) { // Are we matching on the `type`? | 191 | if (config_node->param_type) { // Are we matching on the `type`? |
| 191 | if (config_node->param_type | 192 | if (config_node->param_type && |
| 192 | && config_node->param_type == Z_TYPE_P(arg_value)) { | 193 | config_node->param_type == Z_TYPE_P(arg_value)) { |
| 193 | return true; | 194 | return true; |
| 194 | } | 195 | } |
| 195 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | 196 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { |
| 196 | if (config_node->key || config_node->r_key) { | 197 | if (config_node->key || config_node->r_key) { |
| 197 | if (sp_match_array_key(arg_value, config_node->key, | 198 | if (sp_match_array_key(arg_value, config_node->key, |
| 198 | config_node->r_key)) { | 199 | config_node->r_key)) { |
| 199 | return true; | 200 | return true; |
| 200 | } | 201 | } |
| 201 | } else if (sp_match_array_value(arg_value, config_node->value, | 202 | } else if (sp_match_array_value(arg_value, config_node->value, |
| 202 | config_node->value_r)) { | 203 | config_node->value_r)) { |
| 203 | return true; | 204 | return true; |
| 204 | } | 205 | } |
| 205 | } else if (sp_match_value(*arg_value_str, config_node->value, | 206 | } else if (sp_match_value(*arg_value_str, config_node->value, |
| 206 | config_node->value_r)) { | 207 | config_node->value_r)) { |
| 207 | return true; | 208 | return true; |
| 208 | } | 209 | } |
| 209 | } | 210 | } |
| 210 | } | 211 | } |
| @@ -340,7 +341,7 @@ allow: | |||
| 340 | } | 341 | } |
| 341 | 342 | ||
| 342 | bool should_drop_on_ret(zval* return_value, | 343 | bool should_drop_on_ret(zval* return_value, |
| 343 | const zend_execute_data* const execute_data) { | 344 | const zend_execute_data* const execute_data) { |
| 344 | const sp_list_node* config = | 345 | const sp_list_node* config = |
| 345 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret->disabled_functions; | 346 | SNUFFLEUPAGUS_G(config).config_disabled_functions_ret->disabled_functions; |
| 346 | char* complete_path_function = get_complete_function_path(execute_data); | 347 | char* complete_path_function = get_complete_function_path(execute_data); |
diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h index e43afe8..f80c9c2 100644 --- a/src/sp_disabled_functions.h +++ b/src/sp_disabled_functions.h | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | #define __SP_DISABLE_FUNCTIONS_H | 2 | #define __SP_DISABLE_FUNCTIONS_H |
| 3 | 3 | ||
| 4 | int hook_disabled_functions(); | 4 | int hook_disabled_functions(); |
| 5 | bool should_disable(zend_execute_data*, const char *, const char *, const char *); | 5 | bool should_disable(zend_execute_data *, const char *, const char *, |
| 6 | bool should_drop_on_ret(zval*, const zend_execute_data* const); | 6 | const char *); |
| 7 | bool should_drop_on_ret(zval *, const zend_execute_data *const); | ||
| 7 | 8 | ||
| 8 | #endif /* __SP_DISABLE_FUNCTIONS_H */ | 9 | #endif /* __SP_DISABLE_FUNCTIONS_H */ |
diff --git a/src/sp_execute.c b/src/sp_execute.c index a541bfb..7dd0798 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -7,34 +7,37 @@ ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) | |||
| 7 | 7 | ||
| 8 | static void (*orig_execute_ex)(zend_execute_data *execute_data); | 8 | static void (*orig_execute_ex)(zend_execute_data *execute_data); |
| 9 | static int (*orig_zend_stream_open)(const char *filename, | 9 | static int (*orig_zend_stream_open)(const char *filename, |
| 10 | zend_file_handle *handle); | 10 | zend_file_handle *handle); |
| 11 | 11 | ||
| 12 | // FIXME handle symlink | 12 | // FIXME handle symlink |
| 13 | ZEND_COLD static inline void terminate_if_writable(const char *filename) { | 13 | ZEND_COLD static inline void terminate_if_writable(const char *filename) { |
| 14 | if (0 == access(filename, W_OK)) { | 14 | if (0 == access(filename, W_OK)) { |
| 15 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation) { | 15 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation) { |
| 16 | sp_log_msg("readonly_exec", SP_LOG_SIMULATION, | 16 | sp_log_msg("readonly_exec", SP_LOG_SIMULATION, |
| 17 | "Attempted execution of a writable file (%s).", filename); | 17 | "Attempted execution of a writable file (%s).", filename); |
| 18 | } else { | 18 | } else { |
| 19 | sp_log_msg("readonly_exec", SP_LOG_DROP, | 19 | sp_log_msg("readonly_exec", SP_LOG_DROP, |
| 20 | "Attempted execution of a writable file (%s).", filename); | 20 | "Attempted execution of a writable file (%s).", filename); |
| 21 | sp_terminate(); | 21 | sp_terminate(); |
| 22 | } | 22 | } |
| 23 | } else { | 23 | } else { |
| 24 | if (EACCES != errno) { | 24 | if (EACCES != errno) { |
| 25 | sp_log_err("Writable execution", "Error while accessing %s: %s", filename, | 25 | sp_log_err("Writable execution", "Error while accessing %s: %s", filename, |
| 26 | strerror(errno)); | 26 | strerror(errno)); |
| 27 | } | 27 | } |
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | static void is_builtin_matching(const char * restrict const filename, | 31 | static void is_builtin_matching(const char *restrict const filename, |
| 32 | char* restrict function_name, char* restrict param_name, sp_list_node *config) { | 32 | char *restrict function_name, |
| 33 | char *restrict param_name, | ||
| 34 | sp_list_node *config) { | ||
| 33 | if (!config || !config->data) { | 35 | if (!config || !config->data) { |
| 34 | return; | 36 | return; |
| 35 | } | 37 | } |
| 36 | 38 | ||
| 37 | if (true == should_disable(EG(current_execute_data), function_name, filename, param_name)) { | 39 | if (true == should_disable(EG(current_execute_data), function_name, filename, |
| 40 | param_name)) { | ||
| 38 | sp_terminate(); | 41 | sp_terminate(); |
| 39 | } | 42 | } |
| 40 | } | 43 | } |
| @@ -63,9 +66,10 @@ static void sp_execute_ex(zend_execute_data *execute_data) { | |||
| 63 | if (true == should_disable(execute_data, NULL, NULL, NULL)) { | 66 | if (true == should_disable(execute_data, NULL, NULL, NULL)) { |
| 64 | sp_terminate(); | 67 | sp_terminate(); |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | if (execute_data->func->op_array.type == ZEND_EVAL_CODE) { | 70 | if (execute_data->func->op_array.type == ZEND_EVAL_CODE) { |
| 68 | sp_list_node* config = SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval; | 71 | sp_list_node *config = |
| 72 | SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval; | ||
| 69 | char *filename = get_eval_filename((char *)zend_get_executed_filename()); | 73 | char *filename = get_eval_filename((char *)zend_get_executed_filename()); |
| 70 | is_builtin_matching(filename, "eval", NULL, config); | 74 | is_builtin_matching(filename, "eval", NULL, config); |
| 71 | efree(filename); | 75 | efree(filename); |
| @@ -85,36 +89,40 @@ static void sp_execute_ex(zend_execute_data *execute_data) { | |||
| 85 | } | 89 | } |
| 86 | 90 | ||
| 87 | static int sp_stream_open(const char *filename, zend_file_handle *handle) { | 91 | static int sp_stream_open(const char *filename, zend_file_handle *handle) { |
| 88 | zend_execute_data const * const data = EG(current_execute_data); | 92 | zend_execute_data const *const data = EG(current_execute_data); |
| 89 | 93 | ||
| 90 | if ((NULL == data) || (NULL == data->opline) || (data->func->type != ZEND_USER_FUNCTION)) { | 94 | if ((NULL == data) || (NULL == data->opline) || |
| 95 | (data->func->type != ZEND_USER_FUNCTION)) { | ||
| 91 | goto end; | 96 | goto end; |
| 92 | } | 97 | } |
| 93 | 98 | ||
| 94 | switch(data->opline->opcode) { | 99 | switch (data->opline->opcode) { |
| 95 | case ZEND_INCLUDE_OR_EVAL: | 100 | case ZEND_INCLUDE_OR_EVAL: |
| 96 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { | 101 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { |
| 97 | terminate_if_writable(filename); | 102 | terminate_if_writable(filename); |
| 98 | } | 103 | } |
| 99 | sp_list_node* config = SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include; | 104 | sp_list_node *config = |
| 105 | SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include; | ||
| 100 | switch (data->opline->extended_value) { | 106 | switch (data->opline->extended_value) { |
| 101 | case ZEND_INCLUDE: | 107 | case ZEND_INCLUDE: |
| 102 | is_builtin_matching(filename, "include", "inclusion path", config); | 108 | is_builtin_matching(filename, "include", "inclusion path", config); |
| 103 | break; | 109 | break; |
| 104 | case ZEND_REQUIRE: | 110 | case ZEND_REQUIRE: |
| 105 | is_builtin_matching(filename, "require", "inclusion path", config); | 111 | is_builtin_matching(filename, "require", "inclusion path", config); |
| 106 | break; | 112 | break; |
| 107 | case ZEND_REQUIRE_ONCE: | 113 | case ZEND_REQUIRE_ONCE: |
| 108 | is_builtin_matching(filename, "require_once", "inclusion path", config); | 114 | is_builtin_matching(filename, "require_once", "inclusion path", |
| 109 | break; | 115 | config); |
| 110 | case ZEND_INCLUDE_ONCE: | 116 | break; |
| 111 | is_builtin_matching(filename, "include_once", "inclusion path", config); | 117 | case ZEND_INCLUDE_ONCE: |
| 112 | break; | 118 | is_builtin_matching(filename, "include_once", "inclusion path", |
| 113 | case ZEND_EVAL: | 119 | config); |
| 114 | is_builtin_matching(filename, "eval", NULL, config); | 120 | break; |
| 115 | break; | 121 | case ZEND_EVAL: |
| 116 | default: | 122 | is_builtin_matching(filename, "eval", NULL, config); |
| 117 | break; | 123 | break; |
| 124 | default: | ||
| 125 | break; | ||
| 118 | } | 126 | } |
| 119 | } | 127 | } |
| 120 | 128 | ||
diff --git a/src/sp_list.c b/src/sp_list.c index 2a9d680..447f479 100644 --- a/src/sp_list.c +++ b/src/sp_list.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | #include "php_snuffleupagus.h" | 4 | #include "php_snuffleupagus.h" |
| 5 | 5 | ||
| 6 | void sp_list_free(sp_list_node *node) { | 6 | void sp_list_free(sp_list_node *node) { |
| 7 | while(node) { | 7 | while (node) { |
| 8 | sp_list_node *tmp = node->next; | 8 | sp_list_node *tmp = node->next; |
| 9 | pefree(node, 1); | 9 | pefree(node, 1); |
| 10 | node = tmp; | 10 | node = tmp; |
| @@ -18,7 +18,8 @@ sp_list_node *sp_list_new() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | // Thanks to https://en.wikipedia.org/wiki/Insertion_sort :> | 20 | // Thanks to https://en.wikipedia.org/wiki/Insertion_sort :> |
| 21 | sp_list_node *sp_list_sort(sp_list_node *pList, int (*cmp_func)(sp_list_node *, sp_list_node *)) { | 21 | sp_list_node *sp_list_sort(sp_list_node *pList, |
| 22 | int (*cmp_func)(sp_list_node *, sp_list_node *)) { | ||
| 22 | sp_list_node *head = NULL; | 23 | sp_list_node *head = NULL; |
| 23 | 24 | ||
| 24 | if (pList == NULL || pList->next == NULL) { | 25 | if (pList == NULL || pList->next == NULL) { |
| @@ -33,12 +34,12 @@ sp_list_node *sp_list_sort(sp_list_node *pList, int (*cmp_func)(sp_list_node *, | |||
| 33 | } else { | 34 | } else { |
| 34 | sp_list_node *p = head; | 35 | sp_list_node *p = head; |
| 35 | while (p != NULL) { | 36 | while (p != NULL) { |
| 36 | if (p->next == NULL || 0 > cmp_func(current, p->next)) { | 37 | if (p->next == NULL || 0 > cmp_func(current, p->next)) { |
| 37 | current->next = p->next; | 38 | current->next = p->next; |
| 38 | p->next = current; | 39 | p->next = current; |
| 39 | break; | 40 | break; |
| 40 | } | 41 | } |
| 41 | p = p->next; | 42 | p = p->next; |
| 42 | } | 43 | } |
| 43 | } | 44 | } |
| 44 | } | 45 | } |
diff --git a/src/sp_list.h b/src/sp_list.h index b6760ef..8477463 100644 --- a/src/sp_list.h +++ b/src/sp_list.h | |||
| @@ -9,7 +9,8 @@ typedef struct sp_node_s { | |||
| 9 | } sp_list_node; | 9 | } sp_list_node; |
| 10 | 10 | ||
| 11 | sp_list_node *sp_list_new(); | 11 | sp_list_node *sp_list_new(); |
| 12 | sp_list_node *sp_list_sort(sp_list_node *, int (*)(sp_list_node *, sp_list_node *)); | 12 | sp_list_node *sp_list_sort(sp_list_node *, |
| 13 | int (*)(sp_list_node *, sp_list_node *)); | ||
| 13 | void sp_list_insert(sp_list_node *, void *); | 14 | void sp_list_insert(sp_list_node *, void *); |
| 14 | void sp_list_free(sp_list_node *); | 15 | void sp_list_free(sp_list_node *); |
| 15 | void sp_list_prepend(sp_list_node *, void *); | 16 | void sp_list_prepend(sp_list_node *, void *); |
diff --git a/src/sp_network_utils.c b/src/sp_network_utils.c index 6fc0b1f..51911a8 100644 --- a/src/sp_network_utils.c +++ b/src/sp_network_utils.c | |||
| @@ -91,9 +91,9 @@ int get_ip_and_cidr(char *ip, sp_cidr *cidr) { | |||
| 91 | char *mask = strchr(ip, '/'); | 91 | char *mask = strchr(ip, '/'); |
| 92 | 92 | ||
| 93 | if (NULL == mask) { | 93 | if (NULL == mask) { |
| 94 | sp_log_err("config", | 94 | sp_log_err( |
| 95 | "'%s' isn't a valid network mask, it seems that you forgot a '/'.", | 95 | "config", |
| 96 | ip); | 96 | "'%s' isn't a valid network mask, it seems that you forgot a '/'.", ip); |
| 97 | return -1; | 97 | return -1; |
| 98 | } | 98 | } |
| 99 | 99 | ||
diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c index 7f3add0..312ba2e 100644 --- a/src/sp_unserialize.c +++ b/src/sp_unserialize.c | |||
| @@ -6,11 +6,12 @@ PHP_FUNCTION(sp_serialize) { | |||
| 6 | void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); | 6 | void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); |
| 7 | 7 | ||
| 8 | /* Call the original `serialize` function. */ | 8 | /* Call the original `serialize` function. */ |
| 9 | if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), | 9 | if ((orig_handler = zend_hash_str_find_ptr( |
| 10 | "serialize", 9))) { | 10 | SNUFFLEUPAGUS_G(sp_internal_functions_hook), "serialize", 9))) { |
| 11 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 11 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 12 | } else { | 12 | } else { |
| 13 | sp_log_err("disabled_functions", | 13 | sp_log_err( |
| 14 | "disabled_functions", | ||
| 14 | "Unable to find the pointer to the original function 'serialize' in " | 15 | "Unable to find the pointer to the original function 'serialize' in " |
| 15 | "the hashtable.\n"); | 16 | "the hashtable.\n"); |
| 16 | return; | 17 | return; |
| @@ -57,7 +58,8 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 57 | 58 | ||
| 58 | /* 64 is the length of HMAC-256 */ | 59 | /* 64 is the length of HMAC-256 */ |
| 59 | if (buf_len < 64) { | 60 | if (buf_len < 64) { |
| 60 | sp_log_msg("unserialize", SP_LOG_DROP, "The serialized object is too small."); | 61 | sp_log_msg("unserialize", SP_LOG_DROP, |
| 62 | "The serialized object is too small."); | ||
| 61 | RETURN_FALSE; | 63 | RETURN_FALSE; |
| 62 | } | 64 | } |
| 63 | 65 | ||
| @@ -82,19 +84,22 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | if (0 == status) { | 86 | if (0 == status) { |
| 85 | if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), | 87 | if ((orig_handler = zend_hash_str_find_ptr( |
| 86 | "unserialize", 11))) { | 88 | SNUFFLEUPAGUS_G(sp_internal_functions_hook), "unserialize", 11))) { |
| 87 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 89 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 88 | } | 90 | } |
| 89 | } else { | 91 | } else { |
| 90 | if ( true == SNUFFLEUPAGUS_G(config).config_unserialize->simulation) { | 92 | if (true == SNUFFLEUPAGUS_G(config).config_unserialize->simulation) { |
| 91 | sp_log_msg("unserialize", SP_LOG_SIMULATION, "Invalid HMAC for %s", serialized_str); | 93 | sp_log_msg("unserialize", SP_LOG_SIMULATION, "Invalid HMAC for %s", |
| 92 | if ((orig_handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook), | 94 | serialized_str); |
| 93 | "unserialize", 11))) { | 95 | if ((orig_handler = zend_hash_str_find_ptr( |
| 96 | SNUFFLEUPAGUS_G(sp_internal_functions_hook), "unserialize", | ||
| 97 | 11))) { | ||
| 94 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 98 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 95 | } | 99 | } |
| 96 | } else { | 100 | } else { |
| 97 | sp_log_msg("unserialize", SP_LOG_DROP, "Invalid HMAC for %s", serialized_str); | 101 | sp_log_msg("unserialize", SP_LOG_DROP, "Invalid HMAC for %s", |
| 102 | serialized_str); | ||
| 98 | } | 103 | } |
| 99 | } | 104 | } |
| 100 | efree(serialized_str); | 105 | efree(serialized_str); |
| @@ -104,8 +109,10 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 104 | int hook_serialize(void) { | 109 | int hook_serialize(void) { |
| 105 | TSRMLS_FETCH(); | 110 | TSRMLS_FETCH(); |
| 106 | 111 | ||
| 107 | HOOK_FUNCTION("serialize", sp_internal_functions_hook, PHP_FN(sp_serialize), false); | 112 | HOOK_FUNCTION("serialize", sp_internal_functions_hook, PHP_FN(sp_serialize), |
| 108 | HOOK_FUNCTION("unserialize", sp_internal_functions_hook, PHP_FN(sp_unserialize), false); | 113 | false); |
| 114 | HOOK_FUNCTION("unserialize", sp_internal_functions_hook, | ||
| 115 | PHP_FN(sp_unserialize), false); | ||
| 109 | 116 | ||
| 110 | return SUCCESS; | 117 | return SUCCESS; |
| 111 | } | 118 | } |
diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c index 0010984..4d52266 100644 --- a/src/sp_upload_validation.c +++ b/src/sp_upload_validation.c | |||
| @@ -79,8 +79,9 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) { | |||
| 79 | if (WEXITSTATUS(waitstatus) != 0) { // Nope | 79 | if (WEXITSTATUS(waitstatus) != 0) { // Nope |
| 80 | char *uri = getenv("REQUEST_URI"); | 80 | char *uri = getenv("REQUEST_URI"); |
| 81 | int sim = SNUFFLEUPAGUS_G(config).config_upload_validation->simulation; | 81 | int sim = SNUFFLEUPAGUS_G(config).config_upload_validation->simulation; |
| 82 | sp_log_msg("upload_validation", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | 82 | sp_log_msg("upload_validation", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, |
| 83 | "The upload of %s on %s was rejected.", filename, uri?uri:"?"); | 83 | "The upload of %s on %s was rejected.", filename, |
| 84 | uri ? uri : "?"); | ||
| 84 | if (!SNUFFLEUPAGUS_G(config).config_upload_validation->simulation) { | 85 | if (!SNUFFLEUPAGUS_G(config).config_upload_validation->simulation) { |
| 85 | zend_bailout(); | 86 | zend_bailout(); |
| 86 | } | 87 | } |
diff --git a/src/sp_upload_validation.h b/src/sp_upload_validation.h index 3d59527..ae3871b 100644 --- a/src/sp_upload_validation.h +++ b/src/sp_upload_validation.h | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | void hook_upload(); | 4 | void hook_upload(); |
| 5 | 5 | ||
| 6 | int (*sp_rfc1867_orig_callback)(unsigned int event, void *event_data, void **extra); | 6 | int (*sp_rfc1867_orig_callback)(unsigned int event, void *event_data, |
| 7 | void **extra); | ||
| 7 | int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra); | 8 | int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra); |
| 8 | 9 | ||
| 9 | #endif | 10 | #endif |
diff --git a/src/sp_utils.c b/src/sp_utils.c index 3fe2e44..8a1ed87 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -17,7 +17,7 @@ static inline void _sp_log_err(const char* fmt, ...) { | |||
| 17 | php_log_err(msg); | 17 | php_log_err(msg); |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void sp_log_msg(char const *feature, char const *level, const char* fmt, ...) { | 20 | void sp_log_msg(char const* feature, char const* level, const char* fmt, ...) { |
| 21 | char* msg; | 21 | char* msg; |
| 22 | va_list args; | 22 | va_list args; |
| 23 | 23 | ||
| @@ -25,9 +25,9 @@ void sp_log_msg(char const *feature, char const *level, const char* fmt, ...) { | |||
| 25 | vspprintf(&msg, 0, fmt, args); | 25 | vspprintf(&msg, 0, fmt, args); |
| 26 | va_end(args); | 26 | va_end(args); |
| 27 | 27 | ||
| 28 | char const * const client_ip = getenv("REMOTE_ADDR"); | 28 | char const* const client_ip = getenv("REMOTE_ADDR"); |
| 29 | _sp_log_err("[snuffleupagus][%s][%s][%s] %s", client_ip?client_ip:"0.0.0.0", | 29 | _sp_log_err("[snuffleupagus][%s][%s][%s] %s", |
| 30 | feature, level, msg); | 30 | client_ip ? client_ip : "0.0.0.0", feature, level, msg); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | zend_always_inline int is_regexp_matching(const pcre* regexp, const char* str) { | 33 | zend_always_inline int is_regexp_matching(const pcre* regexp, const char* str) { |
| @@ -38,7 +38,7 @@ zend_always_inline int is_regexp_matching(const pcre* regexp, const char* str) { | |||
| 38 | assert(NULL != str); | 38 | assert(NULL != str); |
| 39 | 39 | ||
| 40 | ret = sp_pcre_exec(regexp, NULL, str, strlen(str), 0, 0, vec, | 40 | ret = sp_pcre_exec(regexp, NULL, str, strlen(str), 0, 0, vec, |
| 41 | sizeof(vec)/sizeof(int)); | 41 | sizeof(vec) / sizeof(int)); |
| 42 | 42 | ||
| 43 | if (ret < 0) { | 43 | if (ret < 0) { |
| 44 | if (ret != PCRE_ERROR_NOMATCH) { | 44 | if (ret != PCRE_ERROR_NOMATCH) { |
| @@ -58,7 +58,8 @@ int compute_hash(const char* const filename, char* file_hash) { | |||
| 58 | php_stream* stream = | 58 | php_stream* stream = |
| 59 | php_stream_open_wrapper(filename, "rb", REPORT_ERRORS, NULL); | 59 | php_stream_open_wrapper(filename, "rb", REPORT_ERRORS, NULL); |
| 60 | if (!stream) { | 60 | if (!stream) { |
| 61 | sp_log_err("hash_computation", "Can not open the file %s to compute its hash.\n", filename); | 61 | sp_log_err("hash_computation", |
| 62 | "Can not open the file %s to compute its hash.\n", filename); | ||
| 62 | return FAILURE; | 63 | return FAILURE; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| @@ -73,14 +74,13 @@ int compute_hash(const char* const filename, char* file_hash) { | |||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | static int construct_filename(char* filename, const char* folder, | 76 | static int construct_filename(char* filename, const char* folder, |
| 76 | const char* textual) { | 77 | const char* textual) { |
| 77 | PHP_SHA256_CTX context; | 78 | PHP_SHA256_CTX context; |
| 78 | unsigned char digest[SHA256_SIZE] = {0}; | 79 | unsigned char digest[SHA256_SIZE] = {0}; |
| 79 | char strhash[65] = {0}; | 80 | char strhash[65] = {0}; |
| 80 | 81 | ||
| 81 | if (-1 == mkdir(folder, 0700) && errno != EEXIST) { | 82 | if (-1 == mkdir(folder, 0700) && errno != EEXIST) { |
| 82 | sp_log_err("request_logging", "Unable to create the folder '%s'.", | 83 | sp_log_err("request_logging", "Unable to create the folder '%s'.", folder); |
| 83 | folder); | ||
| 84 | return -1; | 84 | return -1; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| @@ -88,10 +88,10 @@ static int construct_filename(char* filename, const char* folder, | |||
| 88 | * as filename, in order to only have one dump per rule, to migitate | 88 | * as filename, in order to only have one dump per rule, to migitate |
| 89 | * DoS attacks. */ | 89 | * DoS attacks. */ |
| 90 | PHP_SHA256Init(&context); | 90 | PHP_SHA256Init(&context); |
| 91 | PHP_SHA256Update(&context, (const unsigned char *) textual, strlen(textual)); | 91 | PHP_SHA256Update(&context, (const unsigned char*)textual, strlen(textual)); |
| 92 | PHP_SHA256Final(digest, &context); | 92 | PHP_SHA256Final(digest, &context); |
| 93 | make_digest_ex(strhash, digest, SHA256_SIZE); | 93 | make_digest_ex(strhash, digest, SHA256_SIZE); |
| 94 | snprintf(filename, MAX_FOLDER_LEN-1, "%s/sp_dump.%s", folder, strhash); | 94 | snprintf(filename, MAX_FOLDER_LEN - 1, "%s/sp_dump.%s", folder, strhash); |
| 95 | 95 | ||
| 96 | return 0; | 96 | return 0; |
| 97 | } | 97 | } |
| @@ -106,14 +106,14 @@ int sp_log_request(const char* folder, const char* text_repr) { | |||
| 106 | const int key; | 106 | const int key; |
| 107 | } zones[] = {{"GET", TRACK_VARS_GET}, {"POST", TRACK_VARS_POST}, | 107 | } zones[] = {{"GET", TRACK_VARS_GET}, {"POST", TRACK_VARS_POST}, |
| 108 | {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER}, | 108 | {"COOKIE", TRACK_VARS_COOKIE}, {"SERVER", TRACK_VARS_SERVER}, |
| 109 | {"ENV", TRACK_VARS_ENV}, {NULL, 0}}; | 109 | {"ENV", TRACK_VARS_ENV}, {NULL, 0}}; |
| 110 | 110 | ||
| 111 | if (0 != construct_filename(filename, folder, text_repr)) { | 111 | if (0 != construct_filename(filename, folder, text_repr)) { |
| 112 | return -1; | 112 | return -1; |
| 113 | } | 113 | } |
| 114 | if (NULL == (file = fopen(filename, "w+"))) { | 114 | if (NULL == (file = fopen(filename, "w+"))) { |
| 115 | sp_log_err("request_logging", "Unable to open %s: %s", filename, | 115 | sp_log_err("request_logging", "Unable to open %s: %s", filename, |
| 116 | strerror(errno)); | 116 | strerror(errno)); |
| 117 | return -1; | 117 | return -1; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| @@ -147,7 +147,7 @@ int sp_log_request(const char* folder, const char* text_repr) { | |||
| 147 | return 0; | 147 | return 0; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | static char *zv_str_to_char(zval *zv) { | 150 | static char* zv_str_to_char(zval* zv) { |
| 151 | zval copy; | 151 | zval copy; |
| 152 | 152 | ||
| 153 | ZVAL_ZVAL(©, zv, 1, 0); | 153 | ZVAL_ZVAL(©, zv, 1, 0); |
| @@ -159,7 +159,6 @@ static char *zv_str_to_char(zval *zv) { | |||
| 159 | return estrdup(Z_STRVAL(copy)); | 159 | return estrdup(Z_STRVAL(copy)); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | |||
| 163 | char* sp_convert_to_string(zval* zv) { | 162 | char* sp_convert_to_string(zval* zv) { |
| 164 | switch (Z_TYPE_P(zv)) { | 163 | switch (Z_TYPE_P(zv)) { |
| 165 | case IS_FALSE: | 164 | case IS_FALSE: |
| @@ -169,18 +168,18 @@ char* sp_convert_to_string(zval* zv) { | |||
| 169 | case IS_NULL: | 168 | case IS_NULL: |
| 170 | return estrdup("NULL"); | 169 | return estrdup("NULL"); |
| 171 | case IS_LONG: { | 170 | case IS_LONG: { |
| 172 | char *msg; | 171 | char* msg; |
| 173 | spprintf(&msg, 0, ZEND_LONG_FMT, Z_LVAL_P(zv)); | 172 | spprintf(&msg, 0, ZEND_LONG_FMT, Z_LVAL_P(zv)); |
| 174 | return msg; | 173 | return msg; |
| 175 | } | 174 | } |
| 176 | case IS_DOUBLE: { | 175 | case IS_DOUBLE: { |
| 177 | char *msg; | 176 | char* msg; |
| 178 | spprintf(&msg, 0, "%f", Z_DVAL_P(zv)); | 177 | spprintf(&msg, 0, "%f", Z_DVAL_P(zv)); |
| 179 | return msg; | 178 | return msg; |
| 180 | } | 179 | } |
| 181 | case IS_STRING:{ | 180 | case IS_STRING: { |
| 182 | return zv_str_to_char(zv); | 181 | return zv_str_to_char(zv); |
| 183 | } | 182 | } |
| 184 | case IS_OBJECT: | 183 | case IS_OBJECT: |
| 185 | return estrdup("OBJECT"); | 184 | return estrdup("OBJECT"); |
| 186 | case IS_ARRAY: | 185 | case IS_ARRAY: |
| @@ -212,31 +211,32 @@ void sp_log_disable(const char* restrict path, const char* restrict arg_name, | |||
| 212 | const int sim = config_node->simulation; | 211 | const int sim = config_node->simulation; |
| 213 | if (arg_name) { | 212 | if (arg_name) { |
| 214 | if (alias) { | 213 | if (alias) { |
| 215 | sp_log_msg("disabled_function", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | 214 | sp_log_msg( |
| 215 | "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, | ||
| 216 | "The call to the function '%s' in %s:%d has been disabled, " | 216 | "The call to the function '%s' in %s:%d has been disabled, " |
| 217 | "because its argument '%s' content (%s) matched the rule '%s'.", | 217 | "because its argument '%s' content (%s) matched the rule '%s'.", |
| 218 | path, zend_get_executed_filename(TSRMLS_C), | 218 | path, zend_get_executed_filename(TSRMLS_C), |
| 219 | zend_get_executed_lineno(TSRMLS_C), arg_name, arg_value?arg_value:"?", | ||
| 220 | alias); | ||
| 221 | } else { | ||
| 222 | sp_log_msg("disabled_function", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | ||
| 223 | "The call to the function '%s' in %s:%d has been disabled, " | ||
| 224 | "because its argument '%s' content (%s) matched a rule.", | ||
| 225 | path, zend_get_executed_filename(TSRMLS_C), | ||
| 226 | zend_get_executed_lineno(TSRMLS_C), arg_name, | 219 | zend_get_executed_lineno(TSRMLS_C), arg_name, |
| 227 | arg_value?arg_value:"?"); | 220 | arg_value ? arg_value : "?", alias); |
| 221 | } else { | ||
| 222 | sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, | ||
| 223 | "The call to the function '%s' in %s:%d has been disabled, " | ||
| 224 | "because its argument '%s' content (%s) matched a rule.", | ||
| 225 | path, zend_get_executed_filename(TSRMLS_C), | ||
| 226 | zend_get_executed_lineno(TSRMLS_C), arg_name, | ||
| 227 | arg_value ? arg_value : "?"); | ||
| 228 | } | 228 | } |
| 229 | } else { | 229 | } else { |
| 230 | if (alias) { | 230 | if (alias) { |
| 231 | sp_log_msg("disabled_function", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | 231 | sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, |
| 232 | "The call to the function '%s' in %s:%d has been disabled, " | 232 | "The call to the function '%s' in %s:%d has been disabled, " |
| 233 | "because of the the rule '%s'.",path, | 233 | "because of the the rule '%s'.", |
| 234 | zend_get_executed_filename(TSRMLS_C), | 234 | path, zend_get_executed_filename(TSRMLS_C), |
| 235 | zend_get_executed_lineno(TSRMLS_C), alias); | 235 | zend_get_executed_lineno(TSRMLS_C), alias); |
| 236 | } else { | 236 | } else { |
| 237 | sp_log_msg("disabled_function", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | 237 | sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, |
| 238 | "The call to the function '%s' in %s:%d has been disabled.", | 238 | "The call to the function '%s' in %s:%d has been disabled.", |
| 239 | path, zend_get_executed_filename(TSRMLS_C), | 239 | path, zend_get_executed_filename(TSRMLS_C), |
| 240 | zend_get_executed_lineno(TSRMLS_C)); | 240 | zend_get_executed_lineno(TSRMLS_C)); |
| 241 | } | 241 | } |
| 242 | } | 242 | } |
| @@ -252,17 +252,20 @@ void sp_log_disable_ret(const char* restrict path, | |||
| 252 | const char* alias = config_node->alias; | 252 | const char* alias = config_node->alias; |
| 253 | const int sim = config_node->simulation; | 253 | const int sim = config_node->simulation; |
| 254 | if (alias) { | 254 | if (alias) { |
| 255 | sp_log_msg("disabled_function", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | 255 | sp_log_msg( |
| 256 | "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, | ||
| 256 | "The execution has been aborted in %s:%d, " | 257 | "The execution has been aborted in %s:%d, " |
| 257 | "because the function '%s' returned '%s', which matched the rule '%s'.", | 258 | "because the function '%s' returned '%s', which matched the rule '%s'.", |
| 258 | zend_get_executed_filename(TSRMLS_C), | 259 | zend_get_executed_filename(TSRMLS_C), |
| 259 | zend_get_executed_lineno(TSRMLS_C), path, ret_value?ret_value:"?", alias); | 260 | zend_get_executed_lineno(TSRMLS_C), path, ret_value ? ret_value : "?", |
| 261 | alias); | ||
| 260 | } else { | 262 | } else { |
| 261 | sp_log_msg("disabled_function", sim?SP_LOG_SIMULATION:SP_LOG_DROP, | 263 | sp_log_msg( |
| 264 | "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, | ||
| 262 | "The execution has been aborted in %s:%d, " | 265 | "The execution has been aborted in %s:%d, " |
| 263 | "because the return value (%s) of the function '%s' matched a rule.", | 266 | "because the return value (%s) of the function '%s' matched a rule.", |
| 264 | zend_get_executed_filename(TSRMLS_C), | 267 | zend_get_executed_filename(TSRMLS_C), |
| 265 | zend_get_executed_lineno(TSRMLS_C), ret_value?ret_value:"?", path); | 268 | zend_get_executed_lineno(TSRMLS_C), ret_value ? ret_value : "?", path); |
| 266 | } | 269 | } |
| 267 | if (dump) { | 270 | if (dump) { |
| 268 | sp_log_request(dump, config_node->textual_representation); | 271 | sp_log_request(dump, config_node->textual_representation); |
| @@ -276,17 +279,17 @@ bool sp_match_array_key(const zval* zv, const char* to_match, const pcre* rx) { | |||
| 276 | ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(zv), idx, key) { | 279 | ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(zv), idx, key) { |
| 277 | if (key) { | 280 | if (key) { |
| 278 | if (sp_match_value(ZSTR_VAL(key), to_match, rx)) { | 281 | if (sp_match_value(ZSTR_VAL(key), to_match, rx)) { |
| 279 | return true; | 282 | return true; |
| 280 | } | 283 | } |
| 281 | } else { | 284 | } else { |
| 282 | char *idx_str = NULL; | 285 | char* idx_str = NULL; |
| 283 | 286 | ||
| 284 | // Could use a log. | 287 | // Could use a log. |
| 285 | idx_str = emalloc(snprintf(NULL, 0, "%lu", idx)); | 288 | idx_str = emalloc(snprintf(NULL, 0, "%lu", idx)); |
| 286 | sprintf(idx_str, "%lu", idx); | 289 | sprintf(idx_str, "%lu", idx); |
| 287 | if (sp_match_value(idx_str, to_match, rx)) { | 290 | if (sp_match_value(idx_str, to_match, rx)) { |
| 288 | efree(idx_str); | 291 | efree(idx_str); |
| 289 | return true; | 292 | return true; |
| 290 | } | 293 | } |
| 291 | efree(idx_str); | 294 | efree(idx_str); |
| 292 | } | 295 | } |
| @@ -295,17 +298,18 @@ bool sp_match_array_key(const zval* zv, const char* to_match, const pcre* rx) { | |||
| 295 | return false; | 298 | return false; |
| 296 | } | 299 | } |
| 297 | 300 | ||
| 298 | bool sp_match_array_value(const zval* arr, const char* to_match, const pcre* rx) { | 301 | bool sp_match_array_value(const zval* arr, const char* to_match, |
| 302 | const pcre* rx) { | ||
| 299 | zval* value; | 303 | zval* value; |
| 300 | 304 | ||
| 301 | ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), value) { | 305 | ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), value) { |
| 302 | if (Z_TYPE_P(value) != IS_ARRAY) { | 306 | if (Z_TYPE_P(value) != IS_ARRAY) { |
| 303 | char *value_str = sp_convert_to_string(value); | 307 | char* value_str = sp_convert_to_string(value); |
| 304 | if (sp_match_value(value_str, to_match, rx)) { | 308 | if (sp_match_value(value_str, to_match, rx)) { |
| 305 | efree(value_str); | 309 | efree(value_str); |
| 306 | return true; | 310 | return true; |
| 307 | } else { | 311 | } else { |
| 308 | efree (value_str); | 312 | efree(value_str); |
| 309 | } | 313 | } |
| 310 | } else if (sp_match_array_value(value, to_match, rx)) { | 314 | } else if (sp_match_array_value(value, to_match, rx)) { |
| 311 | return true; | 315 | return true; |
| @@ -315,18 +319,17 @@ bool sp_match_array_value(const zval* arr, const char* to_match, const pcre* rx) | |||
| 315 | return false; | 319 | return false; |
| 316 | } | 320 | } |
| 317 | 321 | ||
| 318 | |||
| 319 | int hook_function(const char* original_name, HashTable* hook_table, | 322 | int hook_function(const char* original_name, HashTable* hook_table, |
| 320 | void (*new_function)(INTERNAL_FUNCTION_PARAMETERS), | 323 | void (*new_function)(INTERNAL_FUNCTION_PARAMETERS), |
| 321 | bool hook_execution_table) { | 324 | bool hook_execution_table) { |
| 322 | zend_internal_function* func; | 325 | zend_internal_function* func; |
| 323 | HashTable *ht = hook_execution_table==true?EG(function_table):CG(function_table); | 326 | HashTable* ht = |
| 327 | hook_execution_table == true ? EG(function_table) : CG(function_table); | ||
| 324 | 328 | ||
| 325 | /* The `mb` module likes to hook functions, like strlen->mb_strlen, | 329 | /* The `mb` module likes to hook functions, like strlen->mb_strlen, |
| 326 | * so we have to hook both of them. */ | 330 | * so we have to hook both of them. */ |
| 327 | 331 | ||
| 328 | if ((func = zend_hash_str_find_ptr(ht, | 332 | if ((func = zend_hash_str_find_ptr(ht, VAR_AND_LEN(original_name)))) { |
| 329 | VAR_AND_LEN(original_name)))) { | ||
| 330 | if (func->handler == new_function) { | 333 | if (func->handler == new_function) { |
| 331 | return SUCCESS; | 334 | return SUCCESS; |
| 332 | } | 335 | } |
| @@ -340,7 +343,7 @@ int hook_function(const char* original_name, HashTable* hook_table, | |||
| 340 | VAR_AND_LEN(original_name), | 343 | VAR_AND_LEN(original_name), |
| 341 | func->handler) == NULL) { | 344 | func->handler) == NULL) { |
| 342 | sp_log_err("function_pointer_saving", | 345 | sp_log_err("function_pointer_saving", |
| 343 | "Could not save function pointer for %s", original_name); | 346 | "Could not save function pointer for %s", original_name); |
| 344 | return FAILURE; | 347 | return FAILURE; |
| 345 | } else { | 348 | } else { |
| 346 | func->handler = new_function; | 349 | func->handler = new_function; |
| @@ -349,9 +352,9 @@ int hook_function(const char* original_name, HashTable* hook_table, | |||
| 349 | 352 | ||
| 350 | if (0 == strncmp(original_name, "mb_", 3)) { | 353 | if (0 == strncmp(original_name, "mb_", 3)) { |
| 351 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; | 354 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; |
| 352 | if (zend_hash_str_find(ht, | 355 | if (zend_hash_str_find(ht, VAR_AND_LEN(original_name + 3))) { |
| 353 | VAR_AND_LEN(original_name + 3))) { | 356 | hook_function(original_name + 3, hook_table, new_function, |
| 354 | hook_function(original_name + 3, hook_table, new_function, hook_execution_table); | 357 | hook_execution_table); |
| 355 | } | 358 | } |
| 356 | } else { // TODO this can be moved somewhere else to gain some marginal perfs | 359 | } else { // TODO this can be moved somewhere else to gain some marginal perfs |
| 357 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; | 360 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; |
| @@ -370,13 +373,14 @@ int hook_regexp(const pcre* regexp, HashTable* hook_table, | |||
| 370 | void (*new_function)(INTERNAL_FUNCTION_PARAMETERS), | 373 | void (*new_function)(INTERNAL_FUNCTION_PARAMETERS), |
| 371 | bool hook_execution_table) { | 374 | bool hook_execution_table) { |
| 372 | zend_string* key; | 375 | zend_string* key; |
| 373 | HashTable *ht = hook_execution_table==true?EG(function_table):CG(function_table); | 376 | HashTable* ht = |
| 377 | hook_execution_table == true ? EG(function_table) : CG(function_table); | ||
| 374 | 378 | ||
| 375 | ZEND_HASH_FOREACH_STR_KEY(ht, key) { | 379 | ZEND_HASH_FOREACH_STR_KEY(ht, key) { |
| 376 | if (key) { | 380 | if (key) { |
| 377 | int vec[30]; | 381 | int vec[30]; |
| 378 | int ret = sp_pcre_exec(regexp, NULL, key->val, key->len, 0, 0, vec, | 382 | int ret = sp_pcre_exec(regexp, NULL, key->val, key->len, 0, 0, vec, |
| 379 | sizeof(vec)/sizeof(int)); | 383 | sizeof(vec) / sizeof(int)); |
| 380 | if (ret < 0) { /* Error or no match*/ | 384 | if (ret < 0) { /* Error or no match*/ |
| 381 | if (PCRE_ERROR_NOMATCH != ret) { | 385 | if (PCRE_ERROR_NOMATCH != ret) { |
| 382 | sp_log_err("pcre", "Runtime error with pcre, error code: %d", ret); | 386 | sp_log_err("pcre", "Runtime error with pcre, error code: %d", ret); |
diff --git a/src/sp_utils.h b/src/sp_utils.h index e54f307..e055e70 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h | |||
| @@ -9,13 +9,13 @@ | |||
| 9 | #include "sp_list.h" | 9 | #include "sp_list.h" |
| 10 | 10 | ||
| 11 | #if defined(__GNUC__) | 11 | #if defined(__GNUC__) |
| 12 | # if __GNUC__ >= 3 | 12 | #if __GNUC__ >= 3 |
| 13 | # define sp_pure __attribute__((pure)) | 13 | #define sp_pure __attribute__((pure)) |
| 14 | # define sp_const __attribute__((const)) | 14 | #define sp_const __attribute__((const)) |
| 15 | # else | 15 | #else |
| 16 | # define sp_pure | 16 | #define sp_pure |
| 17 | # define sp_const | 17 | #define sp_const |
| 18 | # endif | 18 | #endif |
| 19 | #endif | 19 | #endif |
| 20 | /* The dump filename are of the form | 20 | /* The dump filename are of the form |
| 21 | * `sp_dump_DATE_IPADDR.dump`, with: | 21 | * `sp_dump_DATE_IPADDR.dump`, with: |
| @@ -34,7 +34,8 @@ | |||
| 34 | #define SHA256_SIZE 32 | 34 | #define SHA256_SIZE 32 |
| 35 | 35 | ||
| 36 | #define HOOK_FUNCTION(original_name, hook_table, new_function, execution) \ | 36 | #define HOOK_FUNCTION(original_name, hook_table, new_function, execution) \ |
| 37 | hook_function(original_name, SNUFFLEUPAGUS_G(hook_table), new_function, execution) | 37 | hook_function(original_name, SNUFFLEUPAGUS_G(hook_table), new_function, \ |
| 38 | execution) | ||
| 38 | 39 | ||
| 39 | #define HOOK_FUNCTION_BY_REGEXP(regexp, hook_table, new_function, execution) \ | 40 | #define HOOK_FUNCTION_BY_REGEXP(regexp, hook_table, new_function, execution) \ |
| 40 | hook_regexp(regexp, SNUFFLEUPAGUS_G(hook_table), new_function, execution) | 41 | hook_regexp(regexp, SNUFFLEUPAGUS_G(hook_table), new_function, execution) |
| @@ -46,14 +47,14 @@ | |||
| 46 | 47 | ||
| 47 | #define sp_log_err(feature, ...) sp_log_msg(feature, SP_LOG_ERROR, __VA_ARGS__) | 48 | #define sp_log_err(feature, ...) sp_log_msg(feature, SP_LOG_ERROR, __VA_ARGS__) |
| 48 | #ifdef SP_DEBUG | 49 | #ifdef SP_DEBUG |
| 49 | #define sp_log_debug(...) sp_log_msg("DEBUG", SP_LOG_DEBUG, __VA_ARGS__) | 50 | #define sp_log_debug(...) sp_log_msg("DEBUG", SP_LOG_DEBUG, __VA_ARGS__) |
| 50 | #else | 51 | #else |
| 51 | #define sp_log_debug(...) | 52 | #define sp_log_debug(...) |
| 52 | #endif | 53 | #endif |
| 53 | 54 | ||
| 54 | #define GET_SUFFIX(x) (x==1)?"st":((x==2)?"nd":"th") | 55 | #define GET_SUFFIX(x) (x == 1) ? "st" : ((x == 2) ? "nd" : "th") |
| 55 | 56 | ||
| 56 | void sp_log_msg(char const *feature, char const *level, const char* fmt, ...); | 57 | void sp_log_msg(char const *feature, char const *level, const char *fmt, ...); |
| 57 | int compute_hash(const char *const filename, char *file_hash); | 58 | int compute_hash(const char *const filename, char *file_hash); |
| 58 | char *sp_convert_to_string(zval *); | 59 | char *sp_convert_to_string(zval *); |
| 59 | bool sp_match_value(const char *, const char *, const pcre *); | 60 | bool sp_match_value(const char *, const char *, const pcre *); |
diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c index 3f3dcdc..55cbfc2 100644 --- a/src/sp_var_parser.c +++ b/src/sp_var_parser.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | static int parse_str_tokens(const char *str, const sp_conf_token token, | 3 | static int parse_str_tokens(const char *str, const sp_conf_token token, |
| 4 | sp_list_node *tokens_list) { | 4 | sp_list_node *tokens_list) { |
| 5 | const char *cur_str = str; | 5 | const char *cur_str = str; |
| 6 | 6 | ||
| 7 | while ((cur_str = strchr(cur_str, token.text_repr[0]))) { | 7 | while ((cur_str = strchr(cur_str, token.text_repr[0]))) { |
| @@ -30,23 +30,24 @@ static bool is_var_name_valid(const char *name) { | |||
| 30 | } | 30 | } |
| 31 | if (NULL == regexp_var || NULL == regexp_const) { | 31 | if (NULL == regexp_var || NULL == regexp_const) { |
| 32 | regexp_var = sp_pcre_compile(REGEXP_VAR, PCRE_CASELESS, &pcre_error, | 32 | regexp_var = sp_pcre_compile(REGEXP_VAR, PCRE_CASELESS, &pcre_error, |
| 33 | &pcre_error_offset, NULL); | 33 | &pcre_error_offset, NULL); |
| 34 | regexp_const = sp_pcre_compile(REGEXP_CONST, PCRE_CASELESS, &pcre_error, | 34 | regexp_const = sp_pcre_compile(REGEXP_CONST, PCRE_CASELESS, &pcre_error, |
| 35 | &pcre_error_offset, NULL); | 35 | &pcre_error_offset, NULL); |
| 36 | } | 36 | } |
| 37 | if (NULL == regexp_var || NULL == regexp_const) { | 37 | if (NULL == regexp_var || NULL == regexp_const) { |
| 38 | sp_log_err("config", "Could not compile regexp."); | 38 | sp_log_err("config", "Could not compile regexp."); |
| 39 | return false; | 39 | return false; |
| 40 | } | 40 | } |
| 41 | if (0 > sp_pcre_exec(regexp_var, NULL, name, strlen(name), 0, 0, NULL, 0) | 41 | if (0 > sp_pcre_exec(regexp_var, NULL, name, strlen(name), 0, 0, NULL, 0) && |
| 42 | && 0 > sp_pcre_exec(regexp_const, NULL, name, strlen(name), 0, 0, NULL, 0)) { | 42 | 0 > sp_pcre_exec(regexp_const, NULL, name, strlen(name), 0, 0, NULL, 0)) { |
| 43 | return false; | 43 | return false; |
| 44 | } | 44 | } |
| 45 | return true; | 45 | return true; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static int create_var(sp_tree *tree, const char *restrict value, | 48 | static int create_var(sp_tree *tree, const char *restrict value, |
| 49 | size_t value_len, elem_type _type, const char *restrict idx) { | 49 | size_t value_len, elem_type _type, |
| 50 | const char *restrict idx) { | ||
| 50 | sp_tree *var_node = NULL; | 51 | sp_tree *var_node = NULL; |
| 51 | 52 | ||
| 52 | if (!tree) { | 53 | if (!tree) { |
| @@ -72,7 +73,8 @@ static int create_var(sp_tree *tree, const char *restrict value, | |||
| 72 | sp_log_err("config", "Can't allocate a strndup"); | 73 | sp_log_err("config", "Can't allocate a strndup"); |
| 73 | return -1; | 74 | return -1; |
| 74 | } | 75 | } |
| 75 | if (var_node->type != INTERPRETED_STRING && !is_var_name_valid(var_node->value)) { | 76 | if (var_node->type != INTERPRETED_STRING && |
| 77 | !is_var_name_valid(var_node->value)) { | ||
| 76 | sp_log_err("config", "Invalid var name: %s.", var_node->value); | 78 | sp_log_err("config", "Invalid var name: %s.", var_node->value); |
| 77 | return -1; | 79 | return -1; |
| 78 | } | 80 | } |
| @@ -88,22 +90,23 @@ static int create_var(sp_tree *tree, const char *restrict value, | |||
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | int cmp_tokens(sp_list_node *list1, sp_list_node *list2) { | 92 | int cmp_tokens(sp_list_node *list1, sp_list_node *list2) { |
| 91 | return (((sp_conf_token *)list1->data)->pos | 93 | return (((sp_conf_token *)list1->data)->pos - |
| 92 | - ((sp_conf_token *)list2->data)->pos); | 94 | ((sp_conf_token *)list2->data)->pos); |
| 93 | } | 95 | } |
| 94 | 96 | ||
| 95 | static int is_next_token_empty(sp_conf_token *token, sp_conf_token *token_next, | 97 | static int is_next_token_empty(sp_conf_token *token, sp_conf_token *token_next, |
| 96 | const char * restrict str) { | 98 | const char *restrict str) { |
| 97 | if ((token_next && token_next->pos == token->pos + strlen(token->text_repr)) | 99 | if ((token_next && |
| 98 | || (!token_next && token->pos == strlen(str) - strlen(token->text_repr))) { | 100 | token_next->pos == token->pos + strlen(token->text_repr)) || |
| 101 | (!token_next && token->pos == strlen(str) - strlen(token->text_repr))) { | ||
| 99 | return -1; | 102 | return -1; |
| 100 | } | 103 | } |
| 101 | return 0; | 104 | return 0; |
| 102 | } | 105 | } |
| 103 | 106 | ||
| 104 | static int is_token_valid(sp_list_node *tokens_list, elem_type quote, | 107 | static int is_token_valid(sp_list_node *tokens_list, elem_type quote, |
| 105 | int array_count, const char * restrict str, | 108 | int array_count, const char *restrict str, |
| 106 | size_t pos) { | 109 | size_t pos) { |
| 107 | sp_conf_token *token = (sp_conf_token *)tokens_list->data; | 110 | sp_conf_token *token = (sp_conf_token *)tokens_list->data; |
| 108 | sp_conf_token *token_next = NULL; | 111 | sp_conf_token *token_next = NULL; |
| 109 | 112 | ||
| @@ -114,40 +117,40 @@ static int is_token_valid(sp_list_node *tokens_list, elem_type quote, | |||
| 114 | case LITERAL_STRING: | 117 | case LITERAL_STRING: |
| 115 | case INTERPRETED_STRING: | 118 | case INTERPRETED_STRING: |
| 116 | if (quote == token->type) { | 119 | if (quote == token->type) { |
| 117 | if (token_next) { | 120 | if (token_next) { |
| 118 | if (token_next->pos != token->pos + 1) { | 121 | if (token_next->pos != token->pos + 1) { |
| 119 | return -1; | 122 | return -1; |
| 120 | } | 123 | } |
| 121 | } else if (token->pos != strlen(str) - 1) { | 124 | } else if (token->pos != strlen(str) - 1) { |
| 122 | return -1; | 125 | return -1; |
| 123 | } | 126 | } |
| 124 | } | 127 | } |
| 125 | break; | 128 | break; |
| 126 | case ARRAY_END: | 129 | case ARRAY_END: |
| 127 | if (!quote) { | 130 | if (!quote) { |
| 128 | if (array_count < 1) { | 131 | if (array_count < 1) { |
| 129 | return -1; | 132 | return -1; |
| 130 | } else if (token_next) { | 133 | } else if (token_next) { |
| 131 | if (token_next->type == INTERPRETED_STRING | 134 | if (token_next->type == INTERPRETED_STRING || |
| 132 | || token_next->type == LITERAL_STRING) { | 135 | token_next->type == LITERAL_STRING) { |
| 133 | return -1; | 136 | return -1; |
| 134 | } | 137 | } |
| 135 | } else if (token->pos != strlen(str) - strlen(token->text_repr)) { | 138 | } else if (token->pos != strlen(str) - strlen(token->text_repr)) { |
| 136 | return -1; | 139 | return -1; |
| 137 | } | 140 | } |
| 138 | } | 141 | } |
| 139 | break; | 142 | break; |
| 140 | case OBJECT: | 143 | case OBJECT: |
| 141 | if (!quote && -1 == is_next_token_empty(token, token_next, str)) { | 144 | if (!quote && -1 == is_next_token_empty(token, token_next, str)) { |
| 142 | return -1; | 145 | return -1; |
| 143 | } | 146 | } |
| 144 | if (pos == 0 && *str != VARIABLE_TOKEN) { | 147 | if (pos == 0 && *str != VARIABLE_TOKEN) { |
| 145 | return -1; | 148 | return -1; |
| 146 | } | 149 | } |
| 147 | break; | 150 | break; |
| 148 | case CLASS: | 151 | case CLASS: |
| 149 | if (!quote && -1 == is_next_token_empty(token, token_next, str)) { | 152 | if (!quote && -1 == is_next_token_empty(token, token_next, str)) { |
| 150 | return -1; | 153 | return -1; |
| 151 | } | 154 | } |
| 152 | break; | 155 | break; |
| 153 | default: | 156 | default: |
| @@ -156,8 +159,8 @@ static int is_token_valid(sp_list_node *tokens_list, elem_type quote, | |||
| 156 | return 0; | 159 | return 0; |
| 157 | } | 160 | } |
| 158 | 161 | ||
| 159 | static sp_tree *parse_tokens(const char * restrict str, | 162 | static sp_tree *parse_tokens(const char *restrict str, |
| 160 | sp_list_node *tokens_list) { | 163 | sp_list_node *tokens_list) { |
| 161 | size_t pos = 0; | 164 | size_t pos = 0; |
| 162 | int array_count = 0, pos_idx_start = -1; | 165 | int array_count = 0, pos_idx_start = -1; |
| 163 | elem_type quote = 0; | 166 | elem_type quote = 0; |
| @@ -179,7 +182,9 @@ static sp_tree *parse_tokens(const char * restrict str, | |||
| 179 | } | 182 | } |
| 180 | if (quote == 0) { | 183 | if (quote == 0) { |
| 181 | if (token->type == ARRAY) { | 184 | if (token->type == ARRAY) { |
| 182 | pos_idx_start = (array_count) ? pos_idx_start : (int)(token->pos + strlen(token->text_repr)); | 185 | pos_idx_start = (array_count) |
| 186 | ? pos_idx_start | ||
| 187 | : (int)(token->pos + strlen(token->text_repr)); | ||
| 183 | array_count++; | 188 | array_count++; |
| 184 | } else if (token->type == ARRAY_END) { | 189 | } else if (token->type == ARRAY_END) { |
| 185 | array_count--; | 190 | array_count--; |
| @@ -210,12 +215,12 @@ static sp_tree *parse_tokens(const char * restrict str, | |||
| 210 | } | 215 | } |
| 211 | if (quote != 0) { | 216 | if (quote != 0) { |
| 212 | sp_log_err("config", "Missing a closing quote."); | 217 | sp_log_err("config", "Missing a closing quote."); |
| 213 | error: | 218 | error: |
| 214 | sp_tree_free(tree); | 219 | sp_tree_free(tree); |
| 215 | return NULL; | 220 | return NULL; |
| 216 | } | 221 | } |
| 217 | if (pos != strlen(str) | 222 | if (pos != strlen(str) && |
| 218 | && create_var(tree, &str[pos], strlen(str) - pos, CONSTANT, NULL)) { | 223 | create_var(tree, &str[pos], strlen(str) - pos, CONSTANT, NULL)) { |
| 219 | goto error; | 224 | goto error; |
| 220 | } | 225 | } |
| 221 | return tree; | 226 | return tree; |
| @@ -225,20 +230,19 @@ sp_tree *parse_var(const char *line) { | |||
| 225 | sp_list_node *tokens_list = NULL; | 230 | sp_list_node *tokens_list = NULL; |
| 226 | sp_tree *tree = NULL; | 231 | sp_tree *tree = NULL; |
| 227 | const sp_conf_token delimiter_list[] = { | 232 | const sp_conf_token delimiter_list[] = { |
| 228 | {.type=OBJECT, .text_repr=OBJECT_TOKEN}, | 233 | {.type = OBJECT, .text_repr = OBJECT_TOKEN}, |
| 229 | {.type=ARRAY, .text_repr=ARRAY_TOKEN}, | 234 | {.type = ARRAY, .text_repr = ARRAY_TOKEN}, |
| 230 | {.type=ARRAY_END, .text_repr=ARRAY_END_TOKEN}, | 235 | {.type = ARRAY_END, .text_repr = ARRAY_END_TOKEN}, |
| 231 | {.type=INTERPRETED_STRING, .text_repr=STRING_TOKEN}, | 236 | {.type = INTERPRETED_STRING, .text_repr = STRING_TOKEN}, |
| 232 | {.type=LITERAL_STRING, .text_repr=ESC_STRING_TOKEN}, | 237 | {.type = LITERAL_STRING, .text_repr = ESC_STRING_TOKEN}, |
| 233 | {.type=CLASS, .text_repr=CLASS_TOKEN} | 238 | {.type = CLASS, .text_repr = CLASS_TOKEN}}; |
| 234 | }; | ||
| 235 | |||
| 236 | 239 | ||
| 237 | if (!line) { | 240 | if (!line) { |
| 238 | return NULL; | 241 | return NULL; |
| 239 | } | 242 | } |
| 240 | tokens_list = sp_list_new(); | 243 | tokens_list = sp_list_new(); |
| 241 | for (unsigned int i = 0; i < sizeof(delimiter_list) / sizeof(sp_conf_token); i++) { | 244 | for (unsigned int i = 0; i < sizeof(delimiter_list) / sizeof(sp_conf_token); |
| 245 | i++) { | ||
| 242 | parse_str_tokens(line, delimiter_list[i], tokens_list); | 246 | parse_str_tokens(line, delimiter_list[i], tokens_list); |
| 243 | } | 247 | } |
| 244 | tokens_list = sp_list_sort(tokens_list, cmp_tokens); | 248 | tokens_list = sp_list_sort(tokens_list, cmp_tokens); |
diff --git a/src/sp_var_value.c b/src/sp_var_value.c index 7f74afa..9a23ad9 100644 --- a/src/sp_var_value.c +++ b/src/sp_var_value.c | |||
| @@ -23,16 +23,16 @@ static zval *get_local_var(zend_execute_data *ed, const char *var_name) { | |||
| 23 | zval *value = NULL; | 23 | zval *value = NULL; |
| 24 | 24 | ||
| 25 | while (current) { | 25 | while (current) { |
| 26 | zend_string* key = NULL; | 26 | zend_string *key = NULL; |
| 27 | EG(current_execute_data) = current; | 27 | EG(current_execute_data) = current; |
| 28 | zend_array* symtable = zend_rebuild_symbol_table(); | 28 | zend_array *symtable = zend_rebuild_symbol_table(); |
| 29 | ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { | 29 | ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) { |
| 30 | if (0 == strcmp(var_name, key->val)) { | 30 | if (0 == strcmp(var_name, key->val)) { |
| 31 | if (Z_TYPE_P(value) == IS_INDIRECT) { | 31 | if (Z_TYPE_P(value) == IS_INDIRECT) { |
| 32 | value = Z_INDIRECT_P(value); | 32 | value = Z_INDIRECT_P(value); |
| 33 | } | 33 | } |
| 34 | EG(current_execute_data) = orig_execute_data; | 34 | EG(current_execute_data) = orig_execute_data; |
| 35 | return value; | 35 | return value; |
| 36 | } | 36 | } |
| 37 | } | 37 | } |
| 38 | ZEND_HASH_FOREACH_END(); | 38 | ZEND_HASH_FOREACH_END(); |
| @@ -51,7 +51,7 @@ static zval *get_constant(const char *value) { | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | static zval *get_var_value(zend_execute_data *ed, const char *var_name, | 53 | static zval *get_var_value(zend_execute_data *ed, const char *var_name, |
| 54 | bool is_param) { | 54 | bool is_param) { |
| 55 | zval *zvalue = NULL; | 55 | zval *zvalue = NULL; |
| 56 | 56 | ||
| 57 | if (!var_name) { | 57 | if (!var_name) { |
| @@ -73,14 +73,14 @@ static zval *get_var_value(zend_execute_data *ed, const char *var_name, | |||
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static void *get_entry_hashtable(const HashTable *ht, const char *entry, | 75 | static void *get_entry_hashtable(const HashTable *ht, const char *entry, |
| 76 | size_t entry_len) { | 76 | size_t entry_len) { |
| 77 | zval *zvalue = zend_hash_str_find(ht, entry, entry_len); | 77 | zval *zvalue = zend_hash_str_find(ht, entry, entry_len); |
| 78 | 78 | ||
| 79 | if (!zvalue) { | 79 | if (!zvalue) { |
| 80 | zvalue = zend_hash_index_find(ht, atol(entry)); | 80 | zvalue = zend_hash_index_find(ht, atol(entry)); |
| 81 | } | 81 | } |
| 82 | while (zvalue && (Z_TYPE_P(zvalue) == IS_INDIRECT | 82 | while (zvalue && |
| 83 | || Z_TYPE_P(zvalue) == IS_PTR)) { | 83 | (Z_TYPE_P(zvalue) == IS_INDIRECT || Z_TYPE_P(zvalue) == IS_PTR)) { |
| 84 | if (Z_TYPE_P(zvalue) == IS_INDIRECT) { | 84 | if (Z_TYPE_P(zvalue) == IS_INDIRECT) { |
| 85 | zvalue = Z_INDIRECT_P(zvalue); | 85 | zvalue = Z_INDIRECT_P(zvalue); |
| 86 | } else { | 86 | } else { |
| @@ -91,7 +91,7 @@ static void *get_entry_hashtable(const HashTable *ht, const char *entry, | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static zval *get_array_value(zend_execute_data *ed, zval *zvalue, | 93 | static zval *get_array_value(zend_execute_data *ed, zval *zvalue, |
| 94 | const sp_tree *tree) { | 94 | const sp_tree *tree) { |
| 95 | zval *idx_value, *ret = NULL; | 95 | zval *idx_value, *ret = NULL; |
| 96 | char *idx = NULL; | 96 | char *idx = NULL; |
| 97 | 97 | ||
| @@ -108,7 +108,7 @@ static zval *get_array_value(zend_execute_data *ed, zval *zvalue, | |||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static zval *get_object_property(zend_execute_data *ed, zval *object, | 110 | static zval *get_object_property(zend_execute_data *ed, zval *object, |
| 111 | const char *property, bool is_param) { | 111 | const char *property, bool is_param) { |
| 112 | char *class_name = object->value.obj->ce->name->val; | 112 | char *class_name = object->value.obj->ce->name->val; |
| 113 | HashTable *array = Z_OBJPROP_P(object); | 113 | HashTable *array = Z_OBJPROP_P(object); |
| 114 | zval *zvalue = NULL; | 114 | zval *zvalue = NULL; |
| @@ -131,7 +131,8 @@ static zval *get_object_property(zend_execute_data *ed, zval *object, | |||
| 131 | } | 131 | } |
| 132 | if (!zvalue) { | 132 | if (!zvalue) { |
| 133 | char *private_property = emalloc(strlen(class_name) + 3 + strlen(property)); | 133 | char *private_property = emalloc(strlen(class_name) + 3 + strlen(property)); |
| 134 | len = sprintf(private_property, PRIVATE_PROP_FMT, 0, class_name, 0, property); | 134 | len = |
| 135 | sprintf(private_property, PRIVATE_PROP_FMT, 0, class_name, 0, property); | ||
| 135 | zvalue = get_entry_hashtable(array, private_property, len); | 136 | zvalue = get_entry_hashtable(array, private_property, len); |
| 136 | efree(private_property); | 137 | efree(private_property); |
| 137 | } | 138 | } |
| @@ -149,8 +150,8 @@ static zend_class_entry *get_class(const char *value) { | |||
| 149 | } | 150 | } |
| 150 | 151 | ||
| 151 | static zval *get_unknown_type(const char *restrict value, zval *zvalue, | 152 | static zval *get_unknown_type(const char *restrict value, zval *zvalue, |
| 152 | zend_class_entry *ce, zend_execute_data *ed, | 153 | zend_class_entry *ce, zend_execute_data *ed, |
| 153 | const sp_tree *tree, bool is_param) { | 154 | const sp_tree *tree, bool is_param) { |
| 154 | if (ce) { | 155 | if (ce) { |
| 155 | zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value)); | 156 | zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value)); |
| 156 | ce = NULL; | 157 | ce = NULL; |
| @@ -171,51 +172,50 @@ static zval *get_unknown_type(const char *restrict value, zval *zvalue, | |||
| 171 | return zvalue; | 172 | return zvalue; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | zval *get_value(zend_execute_data *ed, const sp_tree *tree, | 175 | zval *get_value(zend_execute_data *ed, const sp_tree *tree, bool is_param) { |
| 175 | bool is_param) { | ||
| 176 | zval *zvalue = NULL; | 176 | zval *zvalue = NULL; |
| 177 | zend_class_entry *ce = NULL; | 177 | zend_class_entry *ce = NULL; |
| 178 | 178 | ||
| 179 | while (tree) { | 179 | while (tree) { |
| 180 | switch (tree->type) { | 180 | switch (tree->type) { |
| 181 | case ARRAY: | 181 | case ARRAY: |
| 182 | if (ce) { | 182 | if (ce) { |
| 183 | zvalue = get_entry_hashtable(&ce->constants_table, tree->value, | 183 | zvalue = get_entry_hashtable(&ce->constants_table, tree->value, |
| 184 | strlen(tree->value)); | 184 | strlen(tree->value)); |
| 185 | ce = NULL; | 185 | ce = NULL; |
| 186 | } else if (!zvalue) { | 186 | } else if (!zvalue) { |
| 187 | zvalue = get_var_value(ed, tree->value, is_param); | 187 | zvalue = get_var_value(ed, tree->value, is_param); |
| 188 | } else if (Z_TYPE_P(zvalue) == IS_OBJECT) { | 188 | } else if (Z_TYPE_P(zvalue) == IS_OBJECT) { |
| 189 | zvalue = get_object_property(ed, zvalue, tree->value, is_param); | 189 | zvalue = get_object_property(ed, zvalue, tree->value, is_param); |
| 190 | } | 190 | } |
| 191 | zvalue = get_array_value(ed, zvalue, tree); | 191 | zvalue = get_array_value(ed, zvalue, tree); |
| 192 | break; | 192 | break; |
| 193 | case VAR: | 193 | case VAR: |
| 194 | if (zvalue && Z_TYPE_P(zvalue) == IS_OBJECT) { | 194 | if (zvalue && Z_TYPE_P(zvalue) == IS_OBJECT) { |
| 195 | zvalue = get_object_property(ed, zvalue, tree->value, is_param); | 195 | zvalue = get_object_property(ed, zvalue, tree->value, is_param); |
| 196 | } else { | 196 | } else { |
| 197 | zvalue = get_var_value(ed, tree->value, is_param); | 197 | zvalue = get_var_value(ed, tree->value, is_param); |
| 198 | } | 198 | } |
| 199 | break; | 199 | break; |
| 200 | case OBJECT: | 200 | case OBJECT: |
| 201 | if (!zvalue) { | 201 | if (!zvalue) { |
| 202 | zvalue = get_var_value(ed, tree->value, is_param); | 202 | zvalue = get_var_value(ed, tree->value, is_param); |
| 203 | } else if (Z_TYPE_P(zvalue) == IS_OBJECT) { | 203 | } else if (Z_TYPE_P(zvalue) == IS_OBJECT) { |
| 204 | if (0 != strlen(tree->value)) { | 204 | if (0 != strlen(tree->value)) { |
| 205 | zvalue = get_object_property(ed, zvalue, tree->value, is_param); | 205 | zvalue = get_object_property(ed, zvalue, tree->value, is_param); |
| 206 | } | 206 | } |
| 207 | } else { | 207 | } else { |
| 208 | return NULL; | 208 | return NULL; |
| 209 | } | 209 | } |
| 210 | break; | 210 | break; |
| 211 | case CLASS: | 211 | case CLASS: |
| 212 | ce = get_class(tree->value); | 212 | ce = get_class(tree->value); |
| 213 | zvalue = NULL; | 213 | zvalue = NULL; |
| 214 | break; | 214 | break; |
| 215 | default: | 215 | default: |
| 216 | zvalue = get_unknown_type(tree->value, zvalue, ce, ed, tree, is_param); | 216 | zvalue = get_unknown_type(tree->value, zvalue, ce, ed, tree, is_param); |
| 217 | ce = NULL; | 217 | ce = NULL; |
| 218 | break; | 218 | break; |
| 219 | } | 219 | } |
| 220 | if (!zvalue && !ce) { | 220 | if (!zvalue && !ce) { |
| 221 | return NULL; | 221 | return NULL; |
