Skip to content

Commit e705e04

Browse files
committed
stream: add error codes and handler check
1 parent 972d7c7 commit e705e04

File tree

5 files changed

+472
-78
lines changed

5 files changed

+472
-78
lines changed

main/php_streams.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,6 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf);
645645

646646
#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_CC)
647647
#define php_stream_open_wrapper_ex(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_CC)
648-
649-
/* pushes an error message onto the stack for a wrapper instance */
650-
PHPAPI void php_stream_wrapper_log_error(const php_stream_wrapper *wrapper, int options, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
651-
652648
typedef enum {
653649
PHP_STREAM_UNCHANGED = 0, /* orig stream was seekable anyway */
654650
PHP_STREAM_RELEASED = 1, /* newstream should be used; origstream is no longer valid */

main/streams/php_stream_errors.h

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Jakub Zelenka <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
117
#ifndef PHP_STREAM_ERRORS_H
218
#define PHP_STREAM_ERRORS_H
319

@@ -18,11 +34,76 @@ BEGIN_EXTERN_C()
1834
#define PHP_STREAM_ERROR_STORE_TERMINAL 3
1935
#define PHP_STREAM_ERROR_STORE_ALL 4
2036

21-
/* Error code definition for registration */
22-
typedef struct {
23-
int code;
24-
const char *name;
25-
} php_stream_error_code_def;
37+
/* Stream Error Codes*/
38+
/* No error */
39+
#define STREAM_ERROR_CODE_NONE 0
40+
/* Generic unspecified error */
41+
#define STREAM_ERROR_CODE_GENERIC 1
42+
/* Stream I/O operations */
43+
#define STREAM_ERROR_CODE_READ_FAILED 10
44+
#define STREAM_ERROR_CODE_WRITE_FAILED 11
45+
#define STREAM_ERROR_CODE_SEEK_FAILED 12
46+
#define STREAM_ERROR_CODE_SEEK_NOT_SUPPORTED 13
47+
#define STREAM_ERROR_CODE_FLUSH_FAILED 14
48+
#define STREAM_ERROR_CODE_TRUNCATE_FAILED 15
49+
#define STREAM_ERROR_CODE_NOT_WRITABLE 16
50+
#define STREAM_ERROR_CODE_NOT_READABLE 17
51+
/* File system operations */
52+
#define STREAM_ERROR_CODE_NOT_FOUND 30
53+
#define STREAM_ERROR_CODE_PERMISSION_DENIED 31
54+
#define STREAM_ERROR_CODE_ALREADY_EXISTS 32
55+
#define STREAM_ERROR_CODE_INVALID_PATH 33
56+
#define STREAM_ERROR_CODE_PATH_TOO_LONG 34
57+
#define STREAM_ERROR_CODE_UNLINK_FAILED 35
58+
#define STREAM_ERROR_CODE_RENAME_FAILED 36
59+
#define STREAM_ERROR_CODE_MKDIR_FAILED 37
60+
#define STREAM_ERROR_CODE_RMDIR_FAILED 38
61+
#define STREAM_ERROR_CODE_STAT_FAILED 39
62+
#define STREAM_ERROR_CODE_CHMOD_FAILED 40
63+
#define STREAM_ERROR_CODE_CHOWN_FAILED 41
64+
#define STREAM_ERROR_CODE_TOUCH_FAILED 42
65+
#define STREAM_ERROR_CODE_INVALID_MODE 43
66+
#define STREAM_ERROR_CODE_MODE_NOT_SUPPORTED 44
67+
#define STREAM_ERROR_CODE_READONLY 45
68+
#define STREAM_ERROR_CODE_RECURSION_DETECTED 46
69+
/* Wrapper/protocol operations */
70+
#define STREAM_ERROR_CODE_WRAPPER_NOT_FOUND 60
71+
#define STREAM_ERROR_CODE_WRAPPER_DISABLED 61
72+
#define STREAM_ERROR_CODE_PROTOCOL_UNSUPPORTED 62
73+
#define STREAM_ERROR_CODE_WRAPPER_REGISTRATION_FAILED 63
74+
#define STREAM_ERROR_CODE_WRAPPER_UNREGISTRATION_FAILED 64
75+
#define STREAM_ERROR_CODE_WRAPPER_RESTORATION_FAILED 65
76+
/* Filter operations */
77+
#define STREAM_ERROR_CODE_FILTER_NOT_FOUND 80
78+
#define STREAM_ERROR_CODE_FILTER_FAILED 81
79+
/* Cast/conversion operations */
80+
#define STREAM_ERROR_CODE_CAST_FAILED 90
81+
#define STREAM_ERROR_CODE_CAST_NOT_SUPPORTED 91
82+
#define STREAM_ERROR_CODE_MAKE_SEEKABLE_FAILED 92
83+
#define STREAM_ERROR_CODE_BUFFERED_DATA_LOST 93
84+
/* Network/socket operations */
85+
#define STREAM_ERROR_CODE_NETWORK_SEND_FAILED 100
86+
#define STREAM_ERROR_CODE_NETWORK_RECV_FAILED 101
87+
#define STREAM_ERROR_CODE_SSL_NOT_SUPPORTED 102
88+
#define STREAM_ERROR_CODE_SOCKET_PATH_TOO_LONG 103
89+
#define STREAM_ERROR_CODE_OOB_NOT_SUPPORTED 104
90+
#define STREAM_ERROR_CODE_PROTOCOL_ERROR 105
91+
#define STREAM_ERROR_CODE_INVALID_URL 106
92+
#define STREAM_ERROR_CODE_INVALID_RESPONSE 107
93+
#define STREAM_ERROR_CODE_REDIRECT_LIMIT 108
94+
#define STREAM_ERROR_CODE_AUTH_FAILED 109
95+
/* Encoding/decoding operations */
96+
#define STREAM_ERROR_CODE_ENCODING_FAILED 120
97+
#define STREAM_ERROR_CODE_INVALID_FORMAT 121
98+
/* Resource/allocation operations */
99+
#define STREAM_ERROR_CODE_ALLOCATION_FAILED 130
100+
#define STREAM_ERROR_CODE_TEMPORARY_FILE_FAILED 131
101+
/* Locking operations */
102+
#define STREAM_ERROR_CODE_LOCK_FAILED 140
103+
#define STREAM_ERROR_CODE_LOCK_NOT_SUPPORTED 141
104+
/* Userspace stream operations */
105+
#define STREAM_ERROR_CODE_USERSPACE_NOT_IMPLEMENTED 150
106+
#define STREAM_ERROR_CODE_USERSPACE_INVALID_RETURN 151
26107

27108
/* Stored error entry */
28109
typedef struct {
@@ -34,20 +115,6 @@ typedef struct {
34115
bool terminal;
35116
} php_stream_error_entry;
36117

37-
/* Sentinel for error code array termination */
38-
#define PHP_STREAM_ERROR_CODE_END {0, NULL}
39-
40-
/* Error code registration */
41-
PHPAPI void php_stream_wrapper_register_error_codes(
42-
php_stream_wrapper *wrapper,
43-
const php_stream_error_code_def *codes
44-
);
45-
46-
PHPAPI const char *php_stream_wrapper_get_error_name(
47-
php_stream_wrapper *wrapper,
48-
int code
49-
);
50-
51118
/* Main error reporting functions */
52119
PHPAPI void php_stream_wrapper_error(
53120
php_stream_wrapper *wrapper,

main/streams/stream_errors.c

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Jakub Zelenka <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
117
#include "php.h"
218
#include "php_globals.h"
319
#include "php_streams.h"
@@ -26,48 +42,6 @@ static void php_stream_error_list_dtor(zval *item)
2642
efree(list);
2743
}
2844

29-
/* Error code registration */
30-
31-
PHPAPI void php_stream_wrapper_register_error_codes(
32-
php_stream_wrapper *wrapper, const php_stream_error_code_def *codes)
33-
{
34-
if (!php_stream_wrapper_error_codes) {
35-
php_stream_wrapper_error_codes = zend_new_array(8);
36-
}
37-
38-
zval code_table_zv, *code_table;
39-
code_table = zend_hash_index_find(php_stream_wrapper_error_codes, (zend_ulong) wrapper);
40-
41-
if (!code_table) {
42-
code_table = &code_table_zv;
43-
ZVAL_ARR(code_table, zend_new_array(8));
44-
zend_hash_index_update(php_stream_wrapper_error_codes, (zend_ulong) wrapper, code_table);
45-
}
46-
47-
for (const php_stream_error_code_def *def = codes; def->name != NULL; def++) {
48-
zend_string *name = zend_string_init(def->name, strlen(def->name), 1);
49-
zval zv;
50-
ZVAL_STR(&zv, name);
51-
zend_hash_index_update(code_table, def->code, &zv);
52-
}
53-
}
54-
55-
PHPAPI const char *php_stream_wrapper_get_error_name(php_stream_wrapper *wrapper, int code)
56-
{
57-
if (!php_stream_wrapper_error_codes) {
58-
return NULL;
59-
}
60-
61-
zval *code_table = zend_hash_index_find(php_stream_wrapper_error_codes, (zend_ulong) wrapper);
62-
63-
if (!code_table) {
64-
return NULL;
65-
}
66-
67-
zval *error_name = zend_hash_index_find(Z_ARR_P(code_table), code);
68-
return error_name ? Z_STRVAL_P(error_name) : NULL;
69-
}
70-
7145
/* Context option helpers */
7246

7347
static int php_stream_auto_decide_error_store_mode(int error_mode)
@@ -186,10 +160,22 @@ static void php_stream_process_error(php_stream_context *context, const char *wr
186160
/* Call user error handler if set */
187161
if (context) {
188162
zval *handler = php_stream_context_get_option(context, "stream", "error_handler");
189-
if (handler && Z_TYPE_P(handler) == IS_CALLABLE) {
163+
if (handler) {
164+
zend_fcall_info_cache fcc;
165+
char *is_callable_error = NULL;
190166
zval retval;
191167
zval args[5];
192168

169+
if (!zend_is_callable_ex(handler, NULL, 0, NULL, &fcc, &is_callable_error)) {
170+
if (is_callable_error) {
171+
zend_type_error("stream error handler must be a valid callback, %s", is_callable_error);
172+
efree(is_callable_error);
173+
} else {
174+
zend_type_error("stream error must be a valid callback");
175+
}
176+
return;
177+
}
178+
193179
/* Arg 0: wrapper name */
194180
ZVAL_STRING(&args[0], wrapper_name);
195181

@@ -525,10 +511,12 @@ PHPAPI void php_stream_error(
525511
zend_string_release(message);
526512
}
527513

528-
/* StreamException class registration */
514+
/* StreamException class and error constants registration */
529515

530516
PHP_MINIT_FUNCTION(stream_errors)
531517
{
518+
register_stream_errors_symbols(module_number);
519+
532520
php_ce_stream_exception = register_class_StreamException(zend_ce_exception);
533521

534522
return SUCCESS;

0 commit comments

Comments
 (0)