summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvoisin2018-10-06 16:15:00 +0000
committerGitHub2018-10-06 16:15:00 +0000
commitaa550b9abadc109a2c89a7cd6dd047ac2a953027 (patch)
tree1892e9ce8f833f3f13278cd424368fe1b5e26d91
parent228fadf307b167a22ad6ec760f3b2ee2e9f2fee3 (diff)
Bump a bit the coverage
* `setcookie` doesn't always return `true` anymore * clang-format * Cookies with invalid decryption are dropped, but the request isn't anymore * faulty unserialize are now dumpable
-rw-r--r--src/sp_config_keywords.c20
-rw-r--r--src/sp_cookie_encryption.c22
-rw-r--r--src/sp_crypt.c17
-rw-r--r--src/sp_disabled_functions.c37
-rw-r--r--src/sp_disabled_functions.h5
-rw-r--r--src/sp_execute.c83
-rw-r--r--src/sp_pcre_compat.c4
-rw-r--r--src/sp_session.c9
-rw-r--r--src/sp_sloppy.c5
-rw-r--r--src/sp_unserialize.c21
-rw-r--r--src/sp_upload_validation.c32
-rw-r--r--src/sp_utils.c28
-rw-r--r--src/sp_utils.h2
-rw-r--r--src/sp_var_parser.c4
-rw-r--r--src/sp_wrapper.c15
-rw-r--r--src/tests/broken_conf_cookie_encryption_without_encryption_key.phpt14
-rw-r--r--src/tests/broken_conf_cookie_encryption_without_env_var.phpt14
-rw-r--r--src/tests/broken_conf_mutually_exclusive11.phpt14
-rw-r--r--src/tests/broken_conf_mutually_exclusive12.phpt14
-rw-r--r--src/tests/broken_conf_wrapper_whitelist.phpt18
-rw-r--r--src/tests/config/broken_conf_cookie_encryption_without_encryption_key.ini2
-rw-r--r--src/tests/config/broken_conf_cookie_encryption_without_env_var.ini2
-rw-r--r--src/tests/config/broken_conf_mutually_exclusive11.ini1
-rw-r--r--src/tests/config/broken_conf_mutually_exclusive12.ini1
-rw-r--r--src/tests/config/broken_conf_wrapper_whitelist.ini1
-rw-r--r--src/tests/crypt_session_invalid.phpt2
-rw-r--r--src/tests/encrypt_cookies4.phpt7
-rw-r--r--src/tests/encrypt_cookies_empty_env.phpt3
-rw-r--r--src/tests/encrypt_cookies_invalid_decryption.phpt15
-rw-r--r--src/tests/encrypt_regexp_cookies_invalid_decryption.phpt6
30 files changed, 261 insertions, 157 deletions
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c
index 6bb7130..04a3f41 100644
--- a/src/sp_config_keywords.c
+++ b/src/sp_config_keywords.c
@@ -52,12 +52,11 @@ int parse_session(char *line) {
52 return -1; 52 return -1;
53 } else if (0 == 53 } else if (0 ==
54 (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) { 54 (SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)) {
55 sp_log_err( 55 sp_log_err("config",
56 "config", 56 "You're trying to use the session cookie encryption feature "
57 "You're trying to use the session cookie encryption feature " 57 "on line %zu without having set the `.secret_key` option in"
58 "on line %zu without having set the `.encryption_key` option in" 58 "`sp.global`: please set it first",
59 "`sp.global`: please set it first", 59 sp_line_no);
60 sp_line_no);
61 pefree(session, 0); 60 pefree(session, 0);
62 return -1; 61 return -1;
63 } 62 }
@@ -166,7 +165,6 @@ int parse_global(char *line) {
166} 165}
167 166
168static int parse_eval_filter_conf(char *line, sp_list_node **list) { 167static int parse_eval_filter_conf(char *line, sp_list_node **list) {
169 zend_string *rest = NULL;
170 sp_config_eval *eval = SNUFFLEUPAGUS_G(config).config_eval; 168 sp_config_eval *eval = SNUFFLEUPAGUS_G(config).config_eval;
171 169
172 sp_config_functions sp_config_funcs[] = { 170 sp_config_functions sp_config_funcs[] = {
@@ -183,9 +181,6 @@ static int parse_eval_filter_conf(char *line, sp_list_node **list) {
183 return ret; 181 return ret;
184 } 182 }
185 183
186 if (rest != NULL) {
187 pefree(rest, 1);
188 }
189 return SUCCESS; 184 return SUCCESS;
190} 185}
191 186
@@ -286,8 +281,7 @@ int parse_cookie(char *line) {
286 return -1; 281 return -1;
287 } 282 }
288 } 283 }
289 SNUFFLEUPAGUS_G(config) 284 SNUFFLEUPAGUS_G(config).config_cookie->cookies =
290 .config_cookie->cookies =
291 sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, cookie); 285 sp_list_insert(SNUFFLEUPAGUS_G(config).config_cookie->cookies, cookie);
292 return SUCCESS; 286 return SUCCESS;
293} 287}
@@ -350,7 +344,7 @@ int parse_disabled_functions(char *line) {
350 if (X && Y) { \ 344 if (X && Y) { \
351 sp_log_err("config", \ 345 sp_log_err("config", \
352 "Invalid configuration line: 'sp.disabled_functions%s': " \ 346 "Invalid configuration line: 'sp.disabled_functions%s': " \
353 "'.%s' and '.%s' are mutually exclusive on line %zu", \ 347 "'.%s' and '.%s' are mutually exclusive on line %zu", \
354 line, STR1, STR2, sp_line_no); \ 348 line, STR1, STR2, sp_line_no); \
355 return 1; \ 349 return 1; \
356 } 350 }
diff --git a/src/sp_cookie_encryption.c b/src/sp_cookie_encryption.c
index 31dde95..4e5242d 100644
--- a/src/sp_cookie_encryption.c
+++ b/src/sp_cookie_encryption.c
@@ -43,11 +43,12 @@ static zend_string *encrypt_data(zend_string *data) {
43} 43}
44 44
45PHP_FUNCTION(sp_setcookie) { 45PHP_FUNCTION(sp_setcookie) {
46 zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL, *value_enc = NULL, 46 zend_string *name = NULL, *value = NULL, *path = NULL, *domain = NULL,
47 *value_enc = NULL,
47#if PHP_VERSION_ID < 70300 48#if PHP_VERSION_ID < 70300
48 *path_samesite = NULL; 49 *path_samesite = NULL;
49#else 50#else
50 *samesite = NULL; 51 *samesite = NULL;
51#endif 52#endif
52 53
53 zend_long expires = 0; 54 zend_long expires = 0;
@@ -95,7 +96,6 @@ PHP_FUNCTION(sp_setcookie) {
95 value_enc = encrypt_data(value); 96 value_enc = encrypt_data(value);
96 } 97 }
97 98
98
99 if (cookie_node && cookie_node->samesite) { 99 if (cookie_node && cookie_node->samesite) {
100 if (!path) { 100 if (!path) {
101 path = zend_string_init("", 0, 0); 101 path = zend_string_init("", 0, 0);
@@ -112,19 +112,20 @@ PHP_FUNCTION(sp_setcookie) {
112 memcpy(ZSTR_VAL(path_samesite) + ZSTR_LEN(path), cookie_samesite, 112 memcpy(ZSTR_VAL(path_samesite) + ZSTR_LEN(path), cookie_samesite,
113 strlen(cookie_samesite) + 1); 113 strlen(cookie_samesite) + 1);
114#else 114#else
115 cookie_samesite = (cookie_node->samesite == lax) 115 cookie_samesite = (cookie_node->samesite == lax) ? SP_TOKEN_SAMESITE_LAX
116 ? SP_TOKEN_SAMESITE_LAX 116 : SP_TOKEN_SAMESITE_STRICT;
117 : SP_TOKEN_SAMESITE_STRICT;
118 117
119 samesite = zend_string_init(cookie_samesite, strlen(cookie_samesite), 0); 118 samesite = zend_string_init(cookie_samesite, strlen(cookie_samesite), 0);
120#endif 119#endif
121 } 120 }
122 121
123
124#if PHP_VERSION_ID < 70300 122#if PHP_VERSION_ID < 70300
125 if (php_setcookie(name, (value_enc ? value_enc : value), expires, (path_samesite ? path_samesite : path), domain, secure, 1, httponly)) { 123 if (php_setcookie(name, (value_enc ? value_enc : value), expires,
124 (path_samesite ? path_samesite : path), domain, secure, 1,
125 httponly) == SUCCESS) {
126#else 126#else
127 if (php_setcookie(name, (value_enc ? value_enc : value), expires, path, domain, secure, httponly, samesite, 1)) { 127 if (php_setcookie(name, (value_enc ? value_enc : value), expires, path,
128 domain, secure, httponly, samesite, 1) == SUCCESS) {
128#endif 129#endif
129 RETVAL_TRUE; 130 RETVAL_TRUE;
130 } else { 131 } else {
@@ -139,7 +140,6 @@ PHP_FUNCTION(sp_setcookie) {
139 zend_string_release(path_samesite); 140 zend_string_release(path_samesite);
140 } 141 }
141#endif 142#endif
142 RETURN_TRUE; // TODO why always true ?
143} 143}
144 144
145int hook_cookies() { 145int hook_cookies() {
diff --git a/src/sp_crypt.c b/src/sp_crypt.c
index 96a0cc0..b6eaa59 100644
--- a/src/sp_crypt.c
+++ b/src/sp_crypt.c
@@ -27,11 +27,10 @@ void generate_key(unsigned char *key) {
27 if (env_var) { 27 if (env_var) {
28 PHP_SHA256Update(&ctx, (unsigned char *)env_var, strlen(env_var)); 28 PHP_SHA256Update(&ctx, (unsigned char *)env_var, strlen(env_var));
29 } else { 29 } else {
30 sp_log_warn( 30 sp_log_warn("cookie_encryption",
31 "cookie_encryption", 31 "The environment variable '%s' "
32 "The environment variable '%s' " 32 "is empty, cookies are weakly encrypted",
33 "is empty, cookies are weakly encrypted", 33 ZSTR_VAL(env_var_zend));
34 ZSTR_VAL(env_var_zend));
35 } 34 }
36 35
37 if (encryption_key) { 36 if (encryption_key) {
@@ -61,14 +60,16 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) {
61 hash_key ? ZSTR_VAL(hash_key->key) : "the session"); 60 hash_key ? ZSTR_VAL(hash_key->key) : "the session");
62 return ZEND_HASH_APPLY_KEEP; 61 return ZEND_HASH_APPLY_KEEP;
63 } else { 62 } else {
63 // LCOV_EXCL_START
64 sp_log_msg( 64 sp_log_msg(
65 "cookie_encryption", SP_LOG_DROP, 65 "cookie_encryption", SP_LOG_DROP,
66 "Buffer underflow tentative detected in cookie encryption handling"); 66 "Buffer underflow tentative detected in cookie encryption handling");
67 return ZEND_HASH_APPLY_REMOVE; 67 return ZEND_HASH_APPLY_REMOVE;
68 // LCOV_EXCL_STOP
68 } 69 }
69 } 70 }
70 71
71 // LCOV_EXCL_START 72 // LCOV_EXCL_START
72 if (ZSTR_LEN(debase64) + (size_t)crypto_secretbox_ZEROBYTES < 73 if (ZSTR_LEN(debase64) + (size_t)crypto_secretbox_ZEROBYTES <
73 ZSTR_LEN(debase64)) { 74 ZSTR_LEN(debase64)) {
74 if (true == simulation) { 75 if (true == simulation) {
@@ -85,7 +86,7 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) {
85 return ZEND_HASH_APPLY_REMOVE; 86 return ZEND_HASH_APPLY_REMOVE;
86 } 87 }
87 } 88 }
88 // LCOV_EXCL_END 89 // LCOV_EXCL_STOP
89 90
90 generate_key(key); 91 generate_key(key);
91 92
@@ -106,7 +107,7 @@ int decrypt_zval(zval *pDest, bool simulation, zend_hash_key *hash_key) {
106 hash_key ? ZSTR_VAL(hash_key->key) : "the session"); 107 hash_key ? ZSTR_VAL(hash_key->key) : "the session");
107 return ZEND_HASH_APPLY_KEEP; 108 return ZEND_HASH_APPLY_KEEP;
108 } else { 109 } else {
109 sp_log_msg("cookie_encryption", SP_LOG_DROP, 110 sp_log_msg("cookie_encryption", SP_LOG_WARN,
110 "Something went wrong with the decryption of %s", 111 "Something went wrong with the decryption of %s",
111 hash_key ? ZSTR_VAL(hash_key->key) : "the session"); 112 hash_key ? ZSTR_VAL(hash_key->key) : "the session");
112 return ZEND_HASH_APPLY_REMOVE; 113 return ZEND_HASH_APPLY_REMOVE;
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c
index 1589cd4..79dc5a7 100644
--- a/src/sp_disabled_functions.c
+++ b/src/sp_disabled_functions.c
@@ -106,12 +106,12 @@ static bool is_param_matching(zend_execute_data* execute_data,
106 if (config_node->pos > nb_param - 1) { 106 if (config_node->pos > nb_param - 1) {
107 char* complete_function_path = get_complete_function_path(execute_data); 107 char* complete_function_path = get_complete_function_path(execute_data);
108 sp_log_warn("config", 108 sp_log_warn("config",
109 "It seems that you wrote a rule filtering on the " 109 "It seems that you wrote a rule filtering on the "
110 "%d%s argument of the function '%s', but it takes only %d " 110 "%d%s argument of the function '%s', but it takes only %d "
111 "arguments. " 111 "arguments. "
112 "Matching on _all_ arguments instead.", 112 "Matching on _all_ arguments instead.",
113 config_node->pos, GET_SUFFIX(config_node->pos), 113 config_node->pos, GET_SUFFIX(config_node->pos),
114 complete_function_path, nb_param); 114 complete_function_path, nb_param);
115 efree(complete_function_path); 115 efree(complete_function_path);
116 } else { 116 } else {
117 i = config_node->pos; 117 i = config_node->pos;
@@ -209,12 +209,12 @@ static zend_execute_data* is_file_matching(
209 zend_execute_data* ex = execute_data; 209 zend_execute_data* ex = execute_data;
210 if (config_node->filename) { 210 if (config_node->filename) {
211 if (sp_zend_string_equals(current_filename, config_node->filename)) { 211 if (sp_zend_string_equals(current_filename, config_node->filename)) {
212 return ex; 212 return ex; // LCOV_EXCL_LINE
213 } 213 }
214 ITERATE(ex); 214 ITERATE(ex);
215 if (zend_string_equals(ex->func->op_array.filename, 215 if (zend_string_equals(ex->func->op_array.filename,
216 config_node->filename)) { 216 config_node->filename)) {
217 return ex; 217 return ex; // LCOV_EXCL_LINE
218 } 218 }
219 } else if (config_node->r_filename) { 219 } else if (config_node->r_filename) {
220 if (sp_is_regexp_matching_zend(config_node->r_filename, current_filename)) { 220 if (sp_is_regexp_matching_zend(config_node->r_filename, current_filename)) {
@@ -415,8 +415,8 @@ bool should_drop_on_ret_ht(const zval* return_value, const char* function_name,
415 415
416 ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name)); 416 ht_entry = zend_hash_str_find_ptr(ht, function_name, strlen(function_name));
417 417
418 if (ht_entry && should_drop_on_ret(return_value, ht_entry, function_name, 418 if (ht_entry &&
419 execute_data)) { 419 should_drop_on_ret(return_value, ht_entry, function_name, execute_data)) {
420 ret = true; 420 ret = true;
421 } else if (config && config->data) { 421 } else if (config && config->data) {
422 ret = should_drop_on_ret(return_value, config, function_name, execute_data); 422 ret = should_drop_on_ret(return_value, config, function_name, execute_data);
@@ -516,13 +516,12 @@ ZEND_FUNCTION(check_disabled_function) {
516 SNUFFLEUPAGUS_G(disabled_functions_hook), current_function_name, 516 SNUFFLEUPAGUS_G(disabled_functions_hook), current_function_name,
517 strlen(current_function_name)); 517 strlen(current_function_name));
518 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 518 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
519 if (true == 519 if (true == should_drop_on_ret_ht(
520 should_drop_on_ret_ht( 520 return_value, current_function_name,
521 return_value, current_function_name, 521 SNUFFLEUPAGUS_G(config)
522 SNUFFLEUPAGUS_G(config) 522 .config_disabled_functions_reg_ret->disabled_functions,
523 .config_disabled_functions_reg_ret->disabled_functions, 523 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked,
524 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret_hooked, 524 execute_data)) {
525 execute_data)) {
526 zend_bailout(); 525 zend_bailout();
527 } 526 }
528} 527}
@@ -584,7 +583,7 @@ ZEND_FUNCTION(eval_blacklist_callback) {
584 583
585 if (config_eval->dump) { 584 if (config_eval->dump) {
586 sp_log_request(config_eval->dump, config_eval->textual_representation, 585 sp_log_request(config_eval->dump, config_eval->textual_representation,
587 SP_TOKEN_EVAL_BLACKLIST); 586 SP_TOKEN_EVAL_BLACKLIST);
588 } 587 }
589 if (config_eval->simulation) { 588 if (config_eval->simulation) {
590 sp_log_msg("eval", SP_LOG_SIMULATION, 589 sp_log_msg("eval", SP_LOG_SIMULATION,
diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h
index ae1500a..b7901dd 100644
--- a/src/sp_disabled_functions.h
+++ b/src/sp_disabled_functions.h
@@ -9,8 +9,9 @@ bool should_disable(zend_execute_data *, const char *, const zend_string *,
9 const char *, const sp_list_node *, const zend_string *); 9 const char *, const sp_list_node *, const zend_string *);
10bool should_disable_ht(zend_execute_data *, const char *, const zend_string *, 10bool should_disable_ht(zend_execute_data *, const char *, const zend_string *,
11 const char *, const sp_list_node *, const HashTable *); 11 const char *, const sp_list_node *, const HashTable *);
12bool should_drop_on_ret_ht(const zval *, const char *, const sp_list_node *config, 12bool should_drop_on_ret_ht(const zval *, const char *,
13 const HashTable *, zend_execute_data *); 13 const sp_list_node *config, const HashTable *,
14 zend_execute_data *);
14bool should_drop_on_ret(const zval *, const sp_list_node *config, const char *, 15bool should_drop_on_ret(const zval *, const sp_list_node *config, const char *,
15 zend_execute_data *); 16 zend_execute_data *);
16char *get_complete_function_path(zend_execute_data const *const); 17char *get_complete_function_path(zend_execute_data const *const);
diff --git a/src/sp_execute.c b/src/sp_execute.c
index 6ed87cb..6def91b 100644
--- a/src/sp_execute.c
+++ b/src/sp_execute.c
@@ -13,13 +13,14 @@ static int (*orig_zend_stream_open)(const char *filename,
13 13
14// FIXME handle symlink 14// FIXME handle symlink
15ZEND_COLD static inline void terminate_if_writable(const char *filename) { 15ZEND_COLD static inline void terminate_if_writable(const char *filename) {
16 const sp_config_readonly_exec* config_ro_exec = 16 const sp_config_readonly_exec *config_ro_exec =
17 SNUFFLEUPAGUS_G(config).config_readonly_exec; 17 SNUFFLEUPAGUS_G(config).config_readonly_exec;
18 18
19 if (0 == access(filename, W_OK)) { 19 if (0 == access(filename, W_OK)) {
20 if (config_ro_exec->dump) { 20 if (config_ro_exec->dump) {
21 sp_log_request(config_ro_exec->dump, config_ro_exec->textual_representation, 21 sp_log_request(config_ro_exec->dump,
22 SP_TOKEN_READONLY_EXEC); 22 config_ro_exec->textual_representation,
23 SP_TOKEN_READONLY_EXEC);
23 } 24 }
24 if (true == config_ro_exec->simulation) { 25 if (true == config_ro_exec->simulation) {
25 sp_log_msg("readonly_exec", SP_LOG_SIMULATION, 26 sp_log_msg("readonly_exec", SP_LOG_SIMULATION,
@@ -31,8 +32,10 @@ ZEND_COLD static inline void terminate_if_writable(const char *filename) {
31 } 32 }
32 } else { 33 } else {
33 if (EACCES != errno) { 34 if (EACCES != errno) {
35 // LCOV_EXCL_START
34 sp_log_err("Writable execution", "Error while accessing %s: %s", filename, 36 sp_log_err("Writable execution", "Error while accessing %s: %s", filename,
35 strerror(errno)); 37 strerror(errno));
38 // LCOV_EXCL_STOP
36 } 39 }
37 } 40 }
38} 41}
@@ -82,7 +85,7 @@ is_in_eval_and_whitelisted(const zend_execute_data *execute_data) {
82 if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) { 85 if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) {
83 if (config_eval->dump) { 86 if (config_eval->dump) {
84 sp_log_request(config_eval->dump, config_eval->textual_representation, 87 sp_log_request(config_eval->dump, config_eval->textual_representation,
85 SP_TOKEN_EVAL_WHITELIST); 88 SP_TOKEN_EVAL_WHITELIST);
86 } 89 }
87 if (config_eval->simulation) { 90 if (config_eval->simulation) {
88 sp_log_msg( 91 sp_log_msg(
@@ -123,7 +126,7 @@ zend_string *get_eval_filename(const char *const filename) {
123 126
124static void sp_execute_ex(zend_execute_data *execute_data) { 127static void sp_execute_ex(zend_execute_data *execute_data) {
125 is_in_eval_and_whitelisted(execute_data); 128 is_in_eval_and_whitelisted(execute_data);
126 const HashTable* config_disabled_functions = 129 const HashTable *config_disabled_functions =
127 SNUFFLEUPAGUS_G(config).config_disabled_functions; 130 SNUFFLEUPAGUS_G(config).config_disabled_functions;
128 131
129 if (!execute_data) { 132 if (!execute_data) {
@@ -131,11 +134,12 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
131 } 134 }
132 135
133 if (UNEXPECTED(EX(func)->op_array.type == ZEND_EVAL_CODE)) { 136 if (UNEXPECTED(EX(func)->op_array.type == ZEND_EVAL_CODE)) {
134 const sp_list_node * config = zend_hash_str_find_ptr( 137 const sp_list_node *config = zend_hash_str_find_ptr(
135 config_disabled_functions, "eval", sizeof("eval") - 1); 138 config_disabled_functions, "eval", sizeof("eval") - 1);
136 139
137 zend_string *filename = get_eval_filename(zend_get_executed_filename()); 140 zend_string *filename = get_eval_filename(zend_get_executed_filename());
138 is_builtin_matching(filename, "eval", NULL, config, config_disabled_functions); 141 is_builtin_matching(filename, "eval", NULL, config,
142 config_disabled_functions);
139 zend_string_release(filename); 143 zend_string_release(filename);
140 144
141 SNUFFLEUPAGUS_G(in_eval)++; 145 SNUFFLEUPAGUS_G(in_eval)++;
@@ -153,9 +157,9 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
153 if (SNUFFLEUPAGUS_G(config).hook_execute) { 157 if (SNUFFLEUPAGUS_G(config).hook_execute) {
154 char *function_name = get_complete_function_path(execute_data); 158 char *function_name = get_complete_function_path(execute_data);
155 zval ret_val; 159 zval ret_val;
156 const sp_list_node* config_disabled_functions_reg = 160 const sp_list_node *config_disabled_functions_reg =
157 SNUFFLEUPAGUS_G(config).config_disabled_functions_reg 161 SNUFFLEUPAGUS_G(config)
158 ->disabled_functions; 162 .config_disabled_functions_reg->disabled_functions;
159 163
160 if (!function_name) { 164 if (!function_name) {
161 orig_execute_ex(execute_data); 165 orig_execute_ex(execute_data);
@@ -166,10 +170,10 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
166 !execute_data->prev_execute_data->func || 170 !execute_data->prev_execute_data->func ||
167 !ZEND_USER_CODE(execute_data->prev_execute_data->func->type) || 171 !ZEND_USER_CODE(execute_data->prev_execute_data->func->type) ||
168 !execute_data->prev_execute_data->opline) { 172 !execute_data->prev_execute_data->opline) {
169 if (UNEXPECTED(true == 173 if (UNEXPECTED(true == should_disable_ht(execute_data, function_name,
170 should_disable_ht(execute_data, function_name, NULL, NULL, 174 NULL, NULL,
171 config_disabled_functions_reg, 175 config_disabled_functions_reg,
172 config_disabled_functions))) { 176 config_disabled_functions))) {
173 zend_bailout(); 177 zend_bailout();
174 } 178 }
175 } else if ((execute_data->prev_execute_data->opline->opcode == 179 } else if ((execute_data->prev_execute_data->opline->opcode ==
@@ -178,16 +182,17 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
178 ZEND_DO_UCALL || 182 ZEND_DO_UCALL ||
179 execute_data->prev_execute_data->opline->opcode == 183 execute_data->prev_execute_data->opline->opcode ==
180 ZEND_DO_FCALL_BY_NAME)) { 184 ZEND_DO_FCALL_BY_NAME)) {
181 if (UNEXPECTED(true == 185 if (UNEXPECTED(true == should_disable_ht(execute_data, function_name,
182 should_disable_ht(execute_data, function_name, NULL, NULL, 186 NULL, NULL,
183 config_disabled_functions_reg, 187 config_disabled_functions_reg,
184 config_disabled_functions))) { 188 config_disabled_functions))) {
185 zend_bailout(); 189 zend_bailout();
186 } 190 }
187 } 191 }
188 192
189 // When a function's return value isn't used, php doesn't store it in the execute_data, 193 // When a function's return value isn't used, php doesn't store it in the
190 // so we need to use a local variable to be able to match on it later. 194 // execute_data, so we need to use a local variable to be able to match on
195 // it later.
191 if (EX(return_value) == NULL) { 196 if (EX(return_value) == NULL) {
192 memset(&ret_val, 0, sizeof(ret_val)); 197 memset(&ret_val, 0, sizeof(ret_val));
193 EX(return_value) = &ret_val; 198 EX(return_value) = &ret_val;
@@ -196,13 +201,13 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
196 orig_execute_ex(execute_data); 201 orig_execute_ex(execute_data);
197 202
198 if (UNEXPECTED( 203 if (UNEXPECTED(
199 true == 204 true ==
200 should_drop_on_ret_ht( 205 should_drop_on_ret_ht(
201 EX(return_value), function_name, 206 EX(return_value), function_name,
202 SNUFFLEUPAGUS_G(config) 207 SNUFFLEUPAGUS_G(config)
203 .config_disabled_functions_reg_ret->disabled_functions, 208 .config_disabled_functions_reg_ret->disabled_functions,
204 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret, 209 SNUFFLEUPAGUS_G(config).config_disabled_functions_ret,
205 execute_data))) { 210 execute_data))) {
206 zend_bailout(); 211 zend_bailout();
207 } 212 }
208 efree(function_name); 213 efree(function_name);
@@ -213,14 +218,14 @@ static void sp_execute_ex(zend_execute_data *execute_data) {
213 } else { 218 } else {
214 orig_execute_ex(execute_data); 219 orig_execute_ex(execute_data);
215 } 220 }
216
217} 221}
218 222
219static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) { 223static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) {
220 is_in_eval_and_whitelisted(execute_data); 224 is_in_eval_and_whitelisted(execute_data);
221 225
222 if (UNEXPECTED(NULL != orig_zend_execute_internal)) { 226 if (UNEXPECTED(NULL != orig_zend_execute_internal)) {
223 orig_zend_execute_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU); 227 orig_zend_execute_internal(
228 INTERNAL_FUNCTION_PARAM_PASSTHRU); // LCOV_EXCL_LINE
224 } else { 229 } else {
225 EX(func)->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 230 EX(func)->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
226 } 231 }
@@ -235,7 +240,7 @@ static int sp_stream_open(const char *filename, zend_file_handle *handle) {
235 } 240 }
236 241
237 zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); 242 zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0);
238 const HashTable* disabled_functions_hooked = 243 const HashTable *disabled_functions_hooked =
239 SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked; 244 SNUFFLEUPAGUS_G(config).config_disabled_functions_hooked;
240 245
241 switch (data->opline->opcode) { 246 switch (data->opline->opcode) {
@@ -247,32 +252,32 @@ static int sp_stream_open(const char *filename, zend_file_handle *handle) {
247 case ZEND_INCLUDE: 252 case ZEND_INCLUDE:
248 is_builtin_matching( 253 is_builtin_matching(
249 zend_filename, "include", "inclusion path", 254 zend_filename, "include", "inclusion path",
250 zend_hash_str_find_ptr(disabled_functions_hooked, 255 zend_hash_str_find_ptr(disabled_functions_hooked, "include",
251 "include", sizeof("include") - 1), 256 sizeof("include") - 1),
252 disabled_functions_hooked); 257 disabled_functions_hooked);
253 break; 258 break;
254 case ZEND_REQUIRE: 259 case ZEND_REQUIRE:
255 is_builtin_matching( 260 is_builtin_matching(
256 zend_filename, "require", "inclusion path", 261 zend_filename, "require", "inclusion path",
257 zend_hash_str_find_ptr(disabled_functions_hooked, 262 zend_hash_str_find_ptr(disabled_functions_hooked, "require",
258 "require", sizeof("require") - 1), 263 sizeof("require") - 1),
259 disabled_functions_hooked); 264 disabled_functions_hooked);
260 break; 265 break;
261 case ZEND_REQUIRE_ONCE: 266 case ZEND_REQUIRE_ONCE:
262 is_builtin_matching( 267 is_builtin_matching(
263 zend_filename, "require_once", "inclusion path", 268 zend_filename, "require_once", "inclusion path",
264 zend_hash_str_find_ptr(disabled_functions_hooked, 269 zend_hash_str_find_ptr(disabled_functions_hooked, "require_once",
265 "require_once", sizeof("require_once") - 1), 270 sizeof("require_once") - 1),
266 disabled_functions_hooked); 271 disabled_functions_hooked);
267 break; 272 break;
268 case ZEND_INCLUDE_ONCE: 273 case ZEND_INCLUDE_ONCE:
269 is_builtin_matching( 274 is_builtin_matching(
270 zend_filename, "include_once", "inclusion path", 275 zend_filename, "include_once", "inclusion path",
271 zend_hash_str_find_ptr(disabled_functions_hooked, 276 zend_hash_str_find_ptr(disabled_functions_hooked, "include_once",
272 "include_once", sizeof("include_once") - 1), 277 sizeof("include_once") - 1),
273 disabled_functions_hooked); 278 disabled_functions_hooked);
274 break; 279 break;
275 EMPTY_SWITCH_DEFAULT_CASE(); 280 EMPTY_SWITCH_DEFAULT_CASE(); // LCOV_EXCL_LINE
276 } 281 }
277 } 282 }
278 efree(zend_filename); 283 efree(zend_filename);
diff --git a/src/sp_pcre_compat.c b/src/sp_pcre_compat.c
index d58d0c4..233ddc0 100644
--- a/src/sp_pcre_compat.c
+++ b/src/sp_pcre_compat.c
@@ -10,7 +10,7 @@ sp_pcre* sp_pcre_compile(const char* const pattern) {
10 PCRE2_SIZE erroroffset; 10 PCRE2_SIZE erroroffset;
11 ret = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 11 ret = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED,
12 PCRE2_CASELESS, &errornumber, &erroroffset, NULL); 12 PCRE2_CASELESS, &errornumber, &erroroffset, NULL);
13 pcre2_get_error_message(errornumber, pcre_error, sizeof(pcre_error)); 13 pcre2_get_error_message(errornumber, pcre_error, sizeof(pcre_error));
14#else 14#else
15 const char* pcre_error = NULL; 15 const char* pcre_error = NULL;
16 int erroroffset; 16 int erroroffset;
@@ -46,7 +46,9 @@ bool ZEND_HOT sp_is_regexp_matching_len(const sp_pcre* regexp, const char* str,
46#else 46#else
47 if (ret != PCRE_ERROR_NOMATCH) { 47 if (ret != PCRE_ERROR_NOMATCH) {
48#endif 48#endif
49 // LCOV_EXCL_START
49 sp_log_err("regexp", "Something went wrong with a regexp (%d).", ret); 50 sp_log_err("regexp", "Something went wrong with a regexp (%d).", ret);
51 // LCOV_EXCL_STOP
50 } 52 }
51 return false; 53 return false;
52 } 54 }
diff --git a/src/sp_session.c b/src/sp_session.c
index 0f1c0b8..73fda22 100644
--- a/src/sp_session.c
+++ b/src/sp_session.c
@@ -27,10 +27,11 @@ static ZEND_INI_MH((*old_OnUpdateSaveHandler)) = NULL;
27 27
28static int sp_hook_s_read(PS_READ_ARGS) { 28static int sp_hook_s_read(PS_READ_ARGS) {
29 int r = old_s_read(mod_data, key, val, maxlifetime); 29 int r = old_s_read(mod_data, key, val, maxlifetime);
30 const sp_config_session* config_session = SNUFFLEUPAGUS_G(config).config_session; 30 const sp_config_session *config_session =
31 SNUFFLEUPAGUS_G(config).config_session;
31 32
32 if (r == SUCCESS && config_session->encrypt && 33 if (r == SUCCESS && config_session->encrypt && val != NULL && *val != NULL &&
33 val != NULL && *val != NULL && ZSTR_LEN(*val)) { 34 ZSTR_LEN(*val)) {
34 zend_string *orig_val = *val; 35 zend_string *orig_val = *val;
35 zval val_zval; 36 zval val_zval;
36 ZVAL_PSTRINGL(&val_zval, ZSTR_VAL(*val), ZSTR_LEN(*val)); 37 ZVAL_PSTRINGL(&val_zval, ZSTR_VAL(*val), ZSTR_LEN(*val));
@@ -40,7 +41,7 @@ static int sp_hook_s_read(PS_READ_ARGS) {
40 if (config_session->simulation) { 41 if (config_session->simulation) {
41 return ret; 42 return ret;
42 } else { 43 } else {
43 sp_terminate(); 44 zend_bailout();
44 } 45 }
45 } 46 }
46 47
diff --git a/src/sp_sloppy.c b/src/sp_sloppy.c
index 695d2a3..d510181 100644
--- a/src/sp_sloppy.c
+++ b/src/sp_sloppy.c
@@ -36,7 +36,6 @@ ZEND_API zend_op_array* sp_compile_file(zend_file_handle* file_handle,
36 return opline; 36 return opline;
37} 37}
38 38
39
40static void array_handler(INTERNAL_FUNCTION_PARAMETERS, const char* name, 39static void array_handler(INTERNAL_FUNCTION_PARAMETERS, const char* name,
41 size_t size, zif_handler orig_handler, 40 size_t size, zif_handler orig_handler,
42 const char* spec) { 41 const char* spec) {
@@ -55,8 +54,8 @@ static void array_handler(INTERNAL_FUNCTION_PARAMETERS, const char* name,
55 ZVAL_COPY(&params[1], array); 54 ZVAL_COPY(&params[1], array);
56 ZVAL_BOOL(&params[2], 1); 55 ZVAL_BOOL(&params[2], 1);
57 } else { 56 } else {
58 // if there is no array as parameter, don't set strict mode. 57 // if there is no array as parameter, don't set strict mode.
59 // check php's implementation for details. 58 // check php's implementation for details.
60 ZVAL_BOOL(&params[2], 0); 59 ZVAL_BOOL(&params[2], 0);
61 } 60 }
62 61
diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c
index 1b47416..fe738e6 100644
--- a/src/sp_unserialize.c
+++ b/src/sp_unserialize.c
@@ -6,9 +6,9 @@ PHP_FUNCTION(sp_serialize) {
6 zif_handler orig_handler; 6 zif_handler orig_handler;
7 7
8 /* Call the original `serialize` function. */ 8 /* Call the original `serialize` function. */
9 orig_handler = zend_hash_str_find_ptr( 9 orig_handler =
10 SNUFFLEUPAGUS_G(sp_internal_functions_hook), "serialize", 10 zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
11 sizeof("serialize") - 1); 11 "serialize", sizeof("serialize") - 1);
12 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 12 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
13 13
14 /* Compute the HMAC of the textual representation of the serialized data*/ 14 /* Compute the HMAC of the textual representation of the serialized data*/
@@ -26,9 +26,11 @@ PHP_FUNCTION(sp_serialize) {
26 26
27 size_t len = Z_STRLEN_P(return_value) + Z_STRLEN(hmac); 27 size_t len = Z_STRLEN_P(return_value) + Z_STRLEN(hmac);
28 if (len < Z_STRLEN_P(return_value)) { 28 if (len < Z_STRLEN_P(return_value)) {
29 // LCOV_EXCL_START
29 sp_log_err("overflow_error", 30 sp_log_err("overflow_error",
30 "Overflow tentative detected in sp_serialize."); 31 "Overflow tentative detected in sp_serialize.");
31 zend_bailout(); 32 zend_bailout();
33 // LCOV_EXCL_STOP
32 } 34 }
33 zend_string *res = zend_string_alloc(len, 0); 35 zend_string *res = zend_string_alloc(len, 0);
34 36
@@ -51,7 +53,7 @@ PHP_FUNCTION(sp_unserialize) {
51 size_t buf_len = 0; 53 size_t buf_len = 0;
52 zval *opts = NULL; 54 zval *opts = NULL;
53 55
54 const sp_config_unserialize* config_unserialize = 56 const sp_config_unserialize *config_unserialize =
55 SNUFFLEUPAGUS_G(config).config_unserialize; 57 SNUFFLEUPAGUS_G(config).config_unserialize;
56 58
57 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &opts) == 59 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &opts) ==
@@ -63,7 +65,6 @@ PHP_FUNCTION(sp_unserialize) {
63 if (buf_len < 64) { 65 if (buf_len < 64) {
64 sp_log_msg("unserialize", SP_LOG_DROP, 66 sp_log_msg("unserialize", SP_LOG_DROP,
65 "The serialized object is too small."); 67 "The serialized object is too small.");
66 RETURN_FALSE;
67 } 68 }
68 69
69 hmac = buf + buf_len - 64; 70 hmac = buf + buf_len - 64;
@@ -94,6 +95,11 @@ PHP_FUNCTION(sp_unserialize) {
94 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 95 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
95 } 96 }
96 } else { 97 } else {
98 if (config_unserialize->dump) {
99 sp_log_request(config_unserialize->dump,
100 config_unserialize->textual_representation,
101 SP_TOKEN_UNSERIALIZE_HMAC);
102 }
97 if (true == config_unserialize->simulation) { 103 if (true == config_unserialize->simulation) {
98 sp_log_msg("unserialize", SP_LOG_SIMULATION, "Invalid HMAC for %s", 104 sp_log_msg("unserialize", SP_LOG_SIMULATION, "Invalid HMAC for %s",
99 serialized_str); 105 serialized_str);
@@ -107,11 +113,6 @@ PHP_FUNCTION(sp_unserialize) {
107 serialized_str); 113 serialized_str);
108 } 114 }
109 } 115 }
110 if (config_unserialize->dump) {
111 sp_log_request(config_unserialize->dump,
112 config_unserialize->textual_representation,
113 SP_TOKEN_UNSERIALIZE_HMAC);
114 }
115 efree(serialized_str); 116 efree(serialized_str);
116 return; 117 return;
117} 118}
diff --git a/src/sp_upload_validation.c b/src/sp_upload_validation.c
index d04dce4..086723d 100644
--- a/src/sp_upload_validation.c
+++ b/src/sp_upload_validation.c
@@ -21,31 +21,31 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) {
21 21
22 if (event == MULTIPART_EVENT_END) { 22 if (event == MULTIPART_EVENT_END) {
23 zend_string *file_key __attribute__((unused)) = NULL; 23 zend_string *file_key __attribute__((unused)) = NULL;
24 const sp_config_upload_validation* config_upload = 24 const sp_config_upload_validation *config_upload =
25 SNUFFLEUPAGUS_G(config).config_upload_validation; 25 SNUFFLEUPAGUS_G(config).config_upload_validation;
26 zval *file; 26 zval *file;
27 pid_t pid; 27 pid_t pid;
28 28
29 sp_log_debug("Got %d files", 29 sp_log_debug(
30 "Got %d files",
30 zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]))); 31 zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES])));
31 32
32 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]), 33 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL(PG(http_globals)[TRACK_VARS_FILES]),
33 file_key, file) { // for each uploaded file 34 file_key, file) { // for each uploaded file
34 35
35 char *filename = 36 char *filename = Z_STRVAL_P(
36 Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "name", sizeof("name") - 1)); 37 zend_hash_str_find(Z_ARRVAL_P(file), "name", sizeof("name") - 1));
37 char *tmp_name = 38 char *tmp_name = Z_STRVAL_P(zend_hash_str_find(
38 Z_STRVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "tmp_name", sizeof("tmp_name") - 1)); 39 Z_ARRVAL_P(file), "tmp_name", sizeof("tmp_name") - 1));
39 size_t filesize = 40 size_t filesize = Z_LVAL_P(
40 Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "size", sizeof("size") - 1)); 41 zend_hash_str_find(Z_ARRVAL_P(file), "size", sizeof("size") - 1));
41 char *cmd[3] = {0}; 42 char *cmd[3] = {0};
42 char *env[5] = {0}; 43 char *env[5] = {0};
43 44
44 sp_log_debug( 45 sp_log_debug("Filename: %s\nTmpname: %s\nSize: %d\nError: %d\nScript: %s",
45 "Filename: %s\nTmpname: %s\nSize: %d\nError: %d\nScript: %s", 46 filename, tmp_name, filesize,
46 filename, tmp_name, filesize, 47 Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "error", 5)),
47 Z_LVAL_P(zend_hash_str_find(Z_ARRVAL_P(file), "error", 5)), 48 ZSTR_VAL(config_upload->script));
48 ZSTR_VAL(config_upload->script));
49 49
50 cmd[0] = ZSTR_VAL(config_upload->script); 50 cmd[0] = ZSTR_VAL(config_upload->script);
51 cmd[1] = tmp_name; 51 cmd[1] = tmp_name;
@@ -60,10 +60,8 @@ int sp_rfc1867_callback(unsigned int event, void *event_data, void **extra) {
60 60
61 if ((pid = fork()) == 0) { 61 if ((pid = fork()) == 0) {
62 if (execve(ZSTR_VAL(config_upload->script), cmd, env) == -1) { 62 if (execve(ZSTR_VAL(config_upload->script), cmd, env) == -1) {
63 sp_log_warn( 63 sp_log_warn("upload_validation", "Could not call '%s' : %s",
64 "upload_validation", "Could not call '%s' : %s", 64 ZSTR_VAL(config_upload->script), strerror(errno));
65 ZSTR_VAL(config_upload->script),
66 strerror(errno));
67 EFREE_3(env); 65 EFREE_3(env);
68 exit(1); 66 exit(1);
69 } 67 }
diff --git a/src/sp_utils.c b/src/sp_utils.c
index 3e542f7..6634a8e 100644
--- a/src/sp_utils.c
+++ b/src/sp_utils.c
@@ -9,8 +9,7 @@
9 9
10ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus) 10ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)
11 11
12bool sp_zend_string_equals(const zend_string* s1, 12bool sp_zend_string_equals(const zend_string* s1, const zend_string* s2) {
13 const zend_string* s2) {
14 // We can't use `zend_string_equals` here because it doesn't work on 13 // We can't use `zend_string_equals` here because it doesn't work on
15 // `const` zend_string. 14 // `const` zend_string.
16 return ZSTR_LEN(s1) == ZSTR_LEN(s2) && 15 return ZSTR_LEN(s1) == ZSTR_LEN(s2) &&
@@ -37,9 +36,11 @@ int compute_hash(const char* const filename, char* file_hash) {
37 php_stream* stream = 36 php_stream* stream =
38 php_stream_open_wrapper(filename, "rb", REPORT_ERRORS, NULL); 37 php_stream_open_wrapper(filename, "rb", REPORT_ERRORS, NULL);
39 if (!stream) { 38 if (!stream) {
39 // LCOV_EXCL_START
40 sp_log_err("hash_computation", 40 sp_log_err("hash_computation",
41 "Can not open the file %s to compute its hash", filename); 41 "Can not open the file %s to compute its hash", filename);
42 return FAILURE; 42 return FAILURE;
43 // LCOV_EXCL_STOP
43 } 44 }
44 45
45 PHP_SHA256Init(&context); 46 PHP_SHA256Init(&context);
@@ -133,9 +134,11 @@ static char* zend_string_to_char(const zend_string* zs) {
133 // Remove all \0 in a zend_string and replace them with '0' instead. 134 // Remove all \0 in a zend_string and replace them with '0' instead.
134 135
135 if (ZSTR_LEN(zs) + 1 < ZSTR_LEN(zs)) { 136 if (ZSTR_LEN(zs) + 1 < ZSTR_LEN(zs)) {
137 // LCOV_EXCL_START
136 sp_log_err("overflow_error", 138 sp_log_err("overflow_error",
137 "Overflow tentative detected in zend_string_to_char"); 139 "Overflow tentative detected in zend_string_to_char");
138 zend_bailout(); 140 zend_bailout();
141 // LCOV_EXCL_STOP
139 } 142 }
140 143
141 char* copy = ecalloc(ZSTR_LEN(zs) + 1, 1); 144 char* copy = ecalloc(ZSTR_LEN(zs) + 1, 1);
@@ -180,8 +183,9 @@ const zend_string* sp_zval_to_zend_string(const zval* zv) {
180 return zend_string_init("ARRAY", sizeof("ARRAY") - 1, 0); 183 return zend_string_init("ARRAY", sizeof("ARRAY") - 1, 0);
181 case IS_RESOURCE: 184 case IS_RESOURCE:
182 return zend_string_init("RESOURCE", sizeof("RESOURCE") - 1, 0); 185 return zend_string_init("RESOURCE", sizeof("RESOURCE") - 1, 0);
186 default:
187 return zend_string_init("", 0, 0); // LCOV_EXCL_LINE
183 } 188 }
184 return zend_string_init("", 0, 0);
185} 189}
186 190
187bool sp_match_value(const zend_string* value, const zend_string* to_match, 191bool sp_match_value(const zend_string* value, const zend_string* to_match,
@@ -216,12 +220,10 @@ void sp_log_disable(const char* restrict path, const char* restrict arg_name,
216 char_repr = zend_string_to_char(arg_value); 220 char_repr = zend_string_to_char(arg_value);
217 } 221 }
218 if (alias) { 222 if (alias) {
219 sp_log_msg( 223 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP,
220 "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, 224 "Aborted execution on call of the function '%s', "
221 "Aborted execution on call of the function '%s', " 225 "because its argument '%s' content (%s) matched the rule '%s'",
222 "because its argument '%s' content (%s) matched the rule '%s'", 226 path, arg_name, char_repr ? char_repr : "?", ZSTR_VAL(alias));
223 path, arg_name, char_repr ? char_repr : "?",
224 ZSTR_VAL(alias));
225 } else { 227 } else {
226 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, 228 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP,
227 "Aborted execution on call of the function '%s', " 229 "Aborted execution on call of the function '%s', "
@@ -237,8 +239,7 @@ void sp_log_disable(const char* restrict path, const char* restrict arg_name,
237 path, ZSTR_VAL(alias)); 239 path, ZSTR_VAL(alias));
238 } else { 240 } else {
239 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, 241 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP,
240 "Aborted execution on call of the function '%s'", 242 "Aborted execution on call of the function '%s'", path);
241 path);
242 } 243 }
243 } 244 }
244} 245}
@@ -263,8 +264,7 @@ void sp_log_disable_ret(const char* restrict path,
263 "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, 264 "disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP,
264 "Aborted execution on return of the function '%s', " 265 "Aborted execution on return of the function '%s', "
265 "because the function returned '%s', which matched the rule '%s'", 266 "because the function returned '%s', which matched the rule '%s'",
266 path, char_repr ? char_repr : "?", 267 path, char_repr ? char_repr : "?", ZSTR_VAL(alias));
267 ZSTR_VAL(alias));
268 } else { 268 } else {
269 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP, 269 sp_log_msg("disabled_function", sim ? SP_LOG_SIMULATION : SP_LOG_DROP,
270 "Aborted execution on return of the function '%s', " 270 "Aborted execution on return of the function '%s', "
@@ -331,9 +331,11 @@ int hook_function(const char* original_name, HashTable* hook_table,
331 if (func->handler != new_function) { 331 if (func->handler != new_function) {
332 if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name), 332 if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name),
333 func->handler) == NULL) { 333 func->handler) == NULL) {
334 // LCOV_EXCL_START
334 sp_log_err("function_pointer_saving", 335 sp_log_err("function_pointer_saving",
335 "Could not save function pointer for %s", original_name); 336 "Could not save function pointer for %s", original_name);
336 return FAILURE; 337 return FAILURE;
338 // LCOV_EXCL_STOP
337 } 339 }
338 func->handler = new_function; 340 func->handler = new_function;
339 ret = SUCCESS; 341 ret = SUCCESS;
diff --git a/src/sp_utils.h b/src/sp_utils.h
index d835905..200e82c 100644
--- a/src/sp_utils.h
+++ b/src/sp_utils.h
@@ -59,6 +59,6 @@ int hook_regexp(const sp_pcre *, HashTable *, zif_handler);
59bool check_is_in_eval_whitelist(const zend_string *const function_name); 59bool check_is_in_eval_whitelist(const zend_string *const function_name);
60int sp_log_request(const zend_string *folder, const zend_string *text_repr, 60int sp_log_request(const zend_string *folder, const zend_string *text_repr,
61 char *from); 61 char *from);
62bool sp_zend_string_equals(const zend_string* s1, const zend_string* s2); 62bool sp_zend_string_equals(const zend_string *s1, const zend_string *s2);
63 63
64#endif /* SP_UTILS_H */ 64#endif /* SP_UTILS_H */
diff --git a/src/sp_var_parser.c b/src/sp_var_parser.c
index b57386e..72cbc12 100644
--- a/src/sp_var_parser.c
+++ b/src/sp_var_parser.c
@@ -31,7 +31,7 @@ static bool is_var_name_valid(const char *name) {
31 regexp_const = sp_pcre_compile(REGEXP_CONST); 31 regexp_const = sp_pcre_compile(REGEXP_CONST);
32 } 32 }
33 if (NULL == regexp_var || NULL == regexp_const) { 33 if (NULL == regexp_var || NULL == regexp_const) {
34 return false; 34 return false; // LCOV_EXCL_LINE
35 } 35 }
36 if ((false == sp_is_regexp_matching(regexp_var, name)) && 36 if ((false == sp_is_regexp_matching(regexp_var, name)) &&
37 (false == sp_is_regexp_matching(regexp_const, name))) { 37 (false == sp_is_regexp_matching(regexp_const, name))) {
@@ -64,8 +64,10 @@ static int create_var(sp_tree *tree, const char *restrict value,
64 var_node->type = VAR; 64 var_node->type = VAR;
65 } 65 }
66 if (!(var_node->value = pestrndup(value, value_len, 1))) { 66 if (!(var_node->value = pestrndup(value, value_len, 1))) {
67 // LCOV_EXCL_START
67 sp_log_err("config", "Can't allocate a strndup"); 68 sp_log_err("config", "Can't allocate a strndup");
68 return -1; 69 return -1;
70 // LCOV_EXCL_STOP
69 } 71 }
70 if (var_node->type != INTERPRETED_STRING && 72 if (var_node->type != INTERPRETED_STRING &&
71 !is_var_name_valid(var_node->value)) { 73 !is_var_name_valid(var_node->value)) {
diff --git a/src/sp_wrapper.c b/src/sp_wrapper.c
index e336a87..fd47dd6 100644
--- a/src/sp_wrapper.c
+++ b/src/sp_wrapper.c
@@ -7,11 +7,11 @@ static bool wrapper_is_whitelisted(const zend_string *zs) {
7 const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist; 7 const sp_list_node *list = SNUFFLEUPAGUS_G(config).config_wrapper->whitelist;
8 8
9 if (!zs) { 9 if (!zs) {
10 return false; 10 return false; // LCOV_EXCL_LINE
11 } 11 }
12 12
13 while (list) { 13 while (list) {
14 if (zend_string_equals_ci(zs, (const zend_string*)list->data)) { 14 if (zend_string_equals_ci(zs, (const zend_string *)list->data)) {
15 return true; 15 return true;
16 } 16 }
17 list = list->next; 17 list = list->next;
@@ -41,23 +41,24 @@ void sp_disable_wrapper() {
41 41
42 zend_hash_destroy(orig_complete); 42 zend_hash_destroy(orig_complete);
43 pefree(orig_complete, 1); 43 pefree(orig_complete, 1);
44 SNUFFLEUPAGUS_G(config).config_wrapper->num_wrapper = zend_hash_num_elements(orig); 44 SNUFFLEUPAGUS_G(config).config_wrapper->num_wrapper =
45 zend_hash_num_elements(orig);
45} 46}
46 47
47PHP_FUNCTION(sp_stream_wrapper_register) { 48PHP_FUNCTION(sp_stream_wrapper_register) {
48 zif_handler orig_handler; 49 zif_handler orig_handler;
49 zend_string *protocol_name = NULL; 50 zend_string *protocol_name = NULL;
50 51
51 // LCOV_EXCL_BR_START 52 // LCOV_EXCL_BR_START
52 ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 2, EX_NUM_ARGS()); 53 ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 2, EX_NUM_ARGS());
53 Z_PARAM_STR(protocol_name); 54 Z_PARAM_STR(protocol_name);
54 ZEND_PARSE_PARAMETERS_END_EX((void)0); 55 ZEND_PARSE_PARAMETERS_END_EX((void)0);
55 // LCOV_EXCL_BR_END 56 // LCOV_EXCL_BR_END
56 57
57 if (wrapper_is_whitelisted(protocol_name)) { 58 if (wrapper_is_whitelisted(protocol_name)) {
58 orig_handler = zend_hash_str_find_ptr( 59 orig_handler = zend_hash_str_find_ptr(
59 SNUFFLEUPAGUS_G(sp_internal_functions_hook), 60 SNUFFLEUPAGUS_G(sp_internal_functions_hook), "stream_wrapper_register",
60 "stream_wrapper_register", sizeof("stream_wrapper_register") - 1); 61 sizeof("stream_wrapper_register") - 1);
61 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 62 orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
62 } 63 }
63} 64}
diff --git a/src/tests/broken_conf_cookie_encryption_without_encryption_key.phpt b/src/tests/broken_conf_cookie_encryption_without_encryption_key.phpt
new file mode 100644
index 0000000..d0b7c0d
--- /dev/null
+++ b/src/tests/broken_conf_cookie_encryption_without_encryption_key.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Borken configuration - encrypted cookie without encryption key
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_cookie_encryption_without_encryption_key.ini
7--FILE--
8--EXPECT--
9PHP Fatal error: [snuffleupagus][config] You're trying to use the cookie encryption featureon line 2 without having set the `.encryption_key` option in`sp.global`: please set it first in Unknown on line 0
10
11Fatal error: [snuffleupagus][config] You're trying to use the cookie encryption featureon line 2 without having set the `.encryption_key` option in`sp.global`: please set it first in Unknown on line 0
12
13Fatal error: [snuffleupagus][config] Invalid configuration file in Unknown on line 0
14Could not startup.
diff --git a/src/tests/broken_conf_cookie_encryption_without_env_var.phpt b/src/tests/broken_conf_cookie_encryption_without_env_var.phpt
new file mode 100644
index 0000000..af5d471
--- /dev/null
+++ b/src/tests/broken_conf_cookie_encryption_without_env_var.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Borken configuration - encrypted cookie with without cookie env var
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_cookie_encryption_without_env_var.ini
7--FILE--
8--EXPECT--
9PHP Fatal error: [snuffleupagus][config] You're trying to use the cookie encryption featureon line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0
10
11Fatal error: [snuffleupagus][config] You're trying to use the cookie encryption featureon line 2 without having set the `.cookie_env_var` option in`sp.global`: please set it first in Unknown on line 0
12
13Fatal error: [snuffleupagus][config] Invalid configuration file in Unknown on line 0
14Could not startup.
diff --git a/src/tests/broken_conf_mutually_exclusive11.phpt b/src/tests/broken_conf_mutually_exclusive11.phpt
new file mode 100644
index 0000000..507d7fa
--- /dev/null
+++ b/src/tests/broken_conf_mutually_exclusive11.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Broken configuration - ret and var are mutually exclusives
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive11.ini
7--FILE--
8--EXPECT--
9PHP Fatal error: [snuffleupagus][config] Invalid configuration line: 'sp.disabled_functions.function("strcmp").drop().ret("hip").var("hop");':`ret` and `var` are mutually exclusive on line 1 in Unknown on line 0
10
11Fatal error: [snuffleupagus][config] Invalid configuration line: 'sp.disabled_functions.function("strcmp").drop().ret("hip").var("hop");':`ret` and `var` are mutually exclusive on line 1 in Unknown on line 0
12
13Fatal error: [snuffleupagus][config] Invalid configuration file in Unknown on line 0
14Could not startup.
diff --git a/src/tests/broken_conf_mutually_exclusive12.phpt b/src/tests/broken_conf_mutually_exclusive12.phpt
new file mode 100644
index 0000000..d823de9
--- /dev/null
+++ b/src/tests/broken_conf_mutually_exclusive12.phpt
@@ -0,0 +1,14 @@
1--TEST--
2Broken configuration - ret and value are mutually exclusive
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_mutually_exclusive12.ini
7--FILE--
8--EXPECT--
9PHP Fatal error: [snuffleupagus][config] Invalid configuration line: 'sp.disabled_functions.function("strcmp").drop().ret("hip").value("hop");':`ret` and `value` are mutually exclusive on line 1 in Unknown on line 0
10
11Fatal error: [snuffleupagus][config] Invalid configuration line: 'sp.disabled_functions.function("strcmp").drop().ret("hip").value("hop");':`ret` and `value` are mutually exclusive on line 1 in Unknown on line 0
12
13Fatal error: [snuffleupagus][config] Invalid configuration file in Unknown on line 0
14Could not startup.
diff --git a/src/tests/broken_conf_wrapper_whitelist.phpt b/src/tests/broken_conf_wrapper_whitelist.phpt
new file mode 100644
index 0000000..ea147ac
--- /dev/null
+++ b/src/tests/broken_conf_wrapper_whitelist.phpt
@@ -0,0 +1,18 @@
1--TEST--
2Broken configuration with invalid token for wrapper whitelist
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/broken_conf_wrapper_whitelist.ini
7sp.allow_broken_configuration=Off
8--FILE--
9<?php
10echo 1337;
11?>
12--EXPECT--
13PHP Fatal error: [snuffleupagus][config] Trailing chars '.invalid_param();' at the end of '.invalid_param();' on line 1 in Unknown on line 0
14
15Fatal error: [snuffleupagus][config] Trailing chars '.invalid_param();' at the end of '.invalid_param();' on line 1 in Unknown on line 0
16
17Fatal error: [snuffleupagus][config] Invalid configuration file in Unknown on line 0
18Could not startup.
diff --git a/src/tests/config/broken_conf_cookie_encryption_without_encryption_key.ini b/src/tests/config/broken_conf_cookie_encryption_without_encryption_key.ini
new file mode 100644
index 0000000..a100bd8
--- /dev/null
+++ b/src/tests/config/broken_conf_cookie_encryption_without_encryption_key.ini
@@ -0,0 +1,2 @@
1sp.global.cookie_env_var("MY_SUPER_ENV_VAR_YAY");
2sp.cookie.name("my_cookie_name").encrypt();
diff --git a/src/tests/config/broken_conf_cookie_encryption_without_env_var.ini b/src/tests/config/broken_conf_cookie_encryption_without_env_var.ini
new file mode 100644
index 0000000..54cb101
--- /dev/null
+++ b/src/tests/config/broken_conf_cookie_encryption_without_env_var.ini
@@ -0,0 +1,2 @@
1sp.global.secret_key("super secret encryption key");
2sp.cookie.name("my_cookie_name").encrypt();
diff --git a/src/tests/config/broken_conf_mutually_exclusive11.ini b/src/tests/config/broken_conf_mutually_exclusive11.ini
new file mode 100644
index 0000000..cab163f
--- /dev/null
+++ b/src/tests/config/broken_conf_mutually_exclusive11.ini
@@ -0,0 +1 @@
sp.disable_function.function("strcmp").drop().ret("hip").var("hop");
diff --git a/src/tests/config/broken_conf_mutually_exclusive12.ini b/src/tests/config/broken_conf_mutually_exclusive12.ini
new file mode 100644
index 0000000..fe140db
--- /dev/null
+++ b/src/tests/config/broken_conf_mutually_exclusive12.ini
@@ -0,0 +1 @@
sp.disable_function.function("strcmp").drop().ret("hip").value("hop");
diff --git a/src/tests/config/broken_conf_wrapper_whitelist.ini b/src/tests/config/broken_conf_wrapper_whitelist.ini
new file mode 100644
index 0000000..b8e08a8
--- /dev/null
+++ b/src/tests/config/broken_conf_wrapper_whitelist.ini
@@ -0,0 +1 @@
sp.wrappers_whitelist.invalid_param();
diff --git a/src/tests/crypt_session_invalid.phpt b/src/tests/crypt_session_invalid.phpt
index cc6e80e..4b0f4d2 100644
--- a/src/tests/crypt_session_invalid.phpt
+++ b/src/tests/crypt_session_invalid.phpt
@@ -21,4 +21,4 @@ session_start(); // Re start the session, It will read and decrypt the non em
21var_dump($_SESSION); // Dump the session 21var_dump($_SESSION); // Dump the session
22?> 22?>
23--EXPECTF-- 23--EXPECTF--
24Fatal error: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of the session in %s/tests/crypt_session_invalid.php on line %d 24Warning: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of the session in %s/tests/crypt_session_invalid.php on line %d
diff --git a/src/tests/encrypt_cookies4.phpt b/src/tests/encrypt_cookies4.phpt
index 14d737a..04d4076 100644
--- a/src/tests/encrypt_cookies4.phpt
+++ b/src/tests/encrypt_cookies4.phpt
@@ -16,8 +16,13 @@ EOF;
16setcookie("super_cookie", "super_value"); 16setcookie("super_cookie", "super_value");
17setcookie("awful_cookie", "awful_value"); 17setcookie("awful_cookie", "awful_value");
18setcookie("nice_cookie", "nice_value", 1, "1", "1", true, true); 18setcookie("nice_cookie", "nice_value", 1, "1", "1", true, true);
19$ret = setcookie("", "Cookie with no name", 1, "1", "1", true, true);
20if ($ret == TRUE) {
21 echo "fail :/";
22}
19var_dump($_COOKIE); 23var_dump($_COOKIE);
20?> 24?>
21--EXPECT-- 25--EXPECTF--
26Warning: Cookie names must not be empty in %a/tests/encrypt_cookies4.php on line %d
22array(0) { 27array(0) {
23} 28}
diff --git a/src/tests/encrypt_cookies_empty_env.phpt b/src/tests/encrypt_cookies_empty_env.phpt
index 252f831..23f1759 100644
--- a/src/tests/encrypt_cookies_empty_env.phpt
+++ b/src/tests/encrypt_cookies_empty_env.phpt
@@ -14,4 +14,5 @@ super_cookie=cGFkZGluZ3BhZGRpbmdwYWRkaW5ncGFkZGluZ3BhZGRpbmdwYWRkaW5ncGFkZGluZ3B
14--EXPECT-- 14--EXPECT--
15Warning: [snuffleupagus][cookie_encryption] The environment variable 'SUPER_ENV_VAR' is empty, cookies are weakly encrypted in Unknown on line 0 15Warning: [snuffleupagus][cookie_encryption] The environment variable 'SUPER_ENV_VAR' is empty, cookies are weakly encrypted in Unknown on line 0
16 16
17Fatal error: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of super_cookie in Unknown on line 0 17Warning: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of super_cookie in Unknown on line 0
181
diff --git a/src/tests/encrypt_cookies_invalid_decryption.phpt b/src/tests/encrypt_cookies_invalid_decryption.phpt
index c64675d..d4a0b0f 100644
--- a/src/tests/encrypt_cookies_invalid_decryption.phpt
+++ b/src/tests/encrypt_cookies_invalid_decryption.phpt
@@ -1,5 +1,5 @@
1--TEST-- 1--TEST--
2Cookie encryption 2Cookie encryption - invalid decryption
3--SKIPIF-- 3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> 4<?php if (!extension_loaded("snuffleupagus")) die "skip"; ?>
5--INI-- 5--INI--
@@ -8,12 +8,19 @@ display_errors=1
8display_startup_errors=1 8display_startup_errors=1
9error_reporting=E_ALL 9error_reporting=E_ALL
10--COOKIE-- 10--COOKIE--
11super_cookie=jWjORGsgZyqzk3WA63XZBmUoSknXWnXDfAAAAAAAAAAAAAAAAAAAAAA7LiMDfkpP94jDnMVH%2Fm41GeL0Y00q3mbOFYz%2FS9mQGySu;awful_cookie=awful_cookie_value; 11super_cookie=Wk9NR1RISVNJU05PVEVOQ1JZUFRFREFUQUxMV0hBVFRIRUhFTExJU0hIRUxMQVJFWU9VRE9JTkdaT01Hb2htYXliZXRoaXNpc2Fub2xkc2Vzc2lvbmNvb2tpZQo=;awfulcookie=awfulcookievalue;
12--ENV-- 12--ENV--
13return <<<EOF 13return <<<EOF
14REMOTE_ADDR=127.0.0.1 14REMOTE_ADDR=127.0.0.1
15EOF; 15EOF;
16--FILE-- 16--FILE--
17<?php var_dump($_COOKIE); ?> 17<?php
18echo "1337\n";
19var_dump($_COOKIE); ?>
18--EXPECT-- 20--EXPECT--
19Fatal error: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of super_cookie in Unknown on line 0 \ No newline at end of file 21Warning: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of super_cookie in Unknown on line 0
221337
23array(1) {
24 ["awfulcookie"]=>
25 string(16) "awfulcookievalue"
26}
diff --git a/src/tests/encrypt_regexp_cookies_invalid_decryption.phpt b/src/tests/encrypt_regexp_cookies_invalid_decryption.phpt
index 0c02806..d2f9e3c 100644
--- a/src/tests/encrypt_regexp_cookies_invalid_decryption.phpt
+++ b/src/tests/encrypt_regexp_cookies_invalid_decryption.phpt
@@ -16,4 +16,8 @@ EOF;
16--FILE-- 16--FILE--
17<?php var_dump($_COOKIE); ?> 17<?php var_dump($_COOKIE); ?>
18--EXPECT-- 18--EXPECT--
19Fatal error: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of super_cookie in Unknown on line 0 \ No newline at end of file 19Warning: [snuffleupagus][cookie_encryption] Something went wrong with the decryption of super_cookie in Unknown on line 0
20array(1) {
21 ["awful_cookie"]=>
22 string(18) "awful_cookie_value"
23}