Skip to content

Commit f8b291d

Browse files
committed
Merge branch 'master' of git.php.net:/php-src
* 'master' of git.php.net:/php-src: Switch reflection to use smart_str Add smart_str_append_printf Make printf_to_smart_str(ing) the primitive printf operation Export zend_s(tr)pprintf Sync smart_string implementation with smart_str Move smart_string to Zend Fixed bug #73154 Flush stderr on win32 in cli_log_message Fixed bug #73154
2 parents 8c5647e + f3f594a commit f8b291d

30 files changed

+562
-767
lines changed

Zend/zend.c

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "zend_dtrace.h"
3333
#include "zend_virtual_cwd.h"
3434
#include "zend_smart_str.h"
35+
#include "zend_smart_string.h"
3536

3637
#ifdef ZTS
3738
# define GLOBAL_FUNCTION_TABLE global_function_table
@@ -54,8 +55,8 @@ ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle
5455
ZEND_API void (*zend_ticks_function)(int ticks);
5556
ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data);
5657
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args);
57-
size_t (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
58-
zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
58+
void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap);
59+
void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap);
5960
ZEND_API char *(*zend_getenv)(char *name, size_t name_len);
6061
ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len);
6162

@@ -159,6 +160,77 @@ static uint32_t zend_version_info_length;
159160
#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2016 Zend Technologies\n"
160161
#define PRINT_ZVAL_INDENT 4
161162

163+
ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
164+
{
165+
smart_string buf = {0};
166+
167+
/* since there are places where (v)spprintf called without checking for null,
168+
a bit of defensive coding here */
169+
if (!pbuf) {
170+
return 0;
171+
}
172+
173+
zend_printf_to_smart_string(&buf, format, ap);
174+
175+
if (max_len && buf.len > max_len) {
176+
buf.len = max_len;
177+
}
178+
179+
smart_string_0(&buf);
180+
181+
if (buf.c) {
182+
*pbuf = buf.c;
183+
return buf.len;
184+
} else {
185+
*pbuf = estrndup("", 0);
186+
return 0;
187+
}
188+
}
189+
/* }}} */
190+
191+
ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */
192+
{
193+
va_list arg;
194+
size_t len;
195+
196+
va_start(arg, format);
197+
len = zend_vspprintf(message, max_len, format, arg);
198+
va_end(arg);
199+
return len;
200+
}
201+
/* }}} */
202+
203+
ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */
204+
{
205+
smart_str buf = {0};
206+
207+
zend_printf_to_smart_str(&buf, format, ap);
208+
209+
if (!buf.s) {
210+
return ZSTR_EMPTY_ALLOC();
211+
}
212+
213+
if (max_len && ZSTR_LEN(buf.s) > max_len) {
214+
ZSTR_LEN(buf.s) = max_len;
215+
}
216+
217+
smart_str_0(&buf);
218+
return buf.s;
219+
}
220+
/* }}} */
221+
222+
ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */
223+
{
224+
va_list arg;
225+
zend_string *str;
226+
227+
va_start(arg, format);
228+
str = zend_vstrpprintf(max_len, format, arg);
229+
va_end(arg);
230+
return str;
231+
}
232+
/* }}} */
233+
162234
static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent);
163235

164236
static void print_hash(smart_str *buf, HashTable *ht, int indent, zend_bool is_object) /* {{{ */
@@ -684,8 +756,8 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
684756
zend_get_configuration_directive_p = utility_functions->get_configuration_directive;
685757
zend_ticks_function = utility_functions->ticks_function;
686758
zend_on_timeout = utility_functions->on_timeout;
687-
zend_vspprintf = utility_functions->vspprintf_function;
688-
zend_vstrpprintf = utility_functions->vstrpprintf_function;
759+
zend_printf_to_smart_string = utility_functions->printf_to_smart_string_function;
760+
zend_printf_to_smart_str = utility_functions->printf_to_smart_str_function;
689761
zend_getenv = utility_functions->getenv_function;
690762
zend_resolve_path = utility_functions->resolve_path_function;
691763

Zend/zend.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "zend_iterators.h"
3939
#include "zend_stream.h"
4040
#include "zend_smart_str_public.h"
41+
#include "zend_smart_string_public.h"
4142
#include "zend_signal.h"
4243

4344
#define HANDLE_BLOCK_INTERRUPTIONS() ZEND_SIGNAL_BLOCK_INTERRUPTIONS()
@@ -185,8 +186,8 @@ typedef struct _zend_utility_functions {
185186
void (*ticks_function)(int ticks);
186187
void (*on_timeout)(int seconds);
187188
int (*stream_open_function)(const char *filename, zend_file_handle *handle);
188-
size_t (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
189-
zend_string *(*vstrpprintf_function)(size_t max_len, const char *format, va_list ap);
189+
void (*printf_to_smart_string_function)(smart_string *buf, const char *format, va_list ap);
190+
void (*printf_to_smart_str_function)(smart_str *buf, const char *format, va_list ap);
190191
char *(*getenv_function)(char *name, size_t name_len);
191192
zend_string *(*resolve_path_function)(const char *filename, int filename_len);
192193
} zend_utility_functions;
@@ -226,6 +227,11 @@ void zend_set_utility_values(zend_utility_values *utility_values);
226227

227228
ZEND_API ZEND_COLD void _zend_bailout(char *filename, uint32_t lineno);
228229

230+
ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap);
231+
ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 3, 4);
232+
ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap);
233+
ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
234+
229235
ZEND_API char *get_zend_version(void);
230236
ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy);
231237
ZEND_API size_t zend_print_zval(zval *expr, int indent);
@@ -260,8 +266,8 @@ extern ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data)
260266
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
261267
extern ZEND_API void (*zend_on_timeout)(int seconds);
262268
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle);
263-
extern size_t (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
264-
extern zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
269+
extern void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap);
270+
extern void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap);
265271
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len);
266272
extern ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len);
267273

Zend/zend_exceptions.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -651,30 +651,6 @@ ZEND_METHOD(exception, getPrevious)
651651
ZVAL_COPY(return_value, GET_PROPERTY_SILENT(getThis(), ZEND_STR_PREVIOUS));
652652
} /* }}} */
653653

654-
size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */
655-
{
656-
va_list arg;
657-
size_t len;
658-
659-
va_start(arg, format);
660-
len = zend_vspprintf(message, max_len, format, arg);
661-
va_end(arg);
662-
return len;
663-
}
664-
/* }}} */
665-
666-
zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */
667-
{
668-
va_list arg;
669-
zend_string *str;
670-
671-
va_start(arg, format);
672-
str = zend_vstrpprintf(max_len, format, arg);
673-
va_end(arg);
674-
return str;
675-
}
676-
/* }}} */
677-
678654
/* {{{ proto string Exception|Error::__toString()
679655
Obtain the string representation of the Exception object */
680656
ZEND_METHOD(exception, __toString)

Zend/zend_exceptions.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ extern ZEND_API void (*zend_throw_exception_hook)(zval *ex);
6868
/* show an exception using zend_error(severity,...), severity should be E_ERROR */
6969
ZEND_API ZEND_COLD void zend_exception_error(zend_object *exception, int severity);
7070

71-
/* do not export, in php it's available thru spprintf directly */
72-
size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 3, 4);
73-
zend_string *zend_strpprintf(size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
74-
7571
#include "zend_globals.h"
7672

7773
static zend_always_inline void zend_rethrow_exception(zend_execute_data *execute_data)

Zend/zend_smart_str.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,10 @@ ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char
117117
}
118118
}
119119
}
120+
121+
ZEND_API void ZEND_FASTCALL smart_str_append_printf(smart_str *dest, const char *format, ...) {
122+
va_list arg;
123+
va_start(arg, format);
124+
zend_printf_to_smart_str(dest, format, arg);
125+
va_end(arg);
126+
}

Zend/zend_smart_str.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define ZEND_SMART_STR_H
2121

2222
#include <zend.h>
23+
#include "zend_globals.h"
2324
#include "zend_smart_str_public.h"
2425

2526
#define smart_str_appends_ex(dest, src, what) \
@@ -46,6 +47,8 @@ BEGIN_EXTERN_C()
4647
ZEND_API void ZEND_FASTCALL smart_str_erealloc(smart_str *str, size_t len);
4748
ZEND_API void ZEND_FASTCALL smart_str_realloc(smart_str *str, size_t len);
4849
ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char *s, size_t l);
50+
ZEND_API void ZEND_FASTCALL smart_str_append_printf(smart_str *dest, const char *format, ...)
51+
ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
4952

5053
END_EXTERN_C()
5154

@@ -80,6 +83,22 @@ static zend_always_inline void smart_str_0(smart_str *str) {
8083
}
8184
}
8285

86+
static zend_always_inline size_t smart_str_get_len(smart_str *str) {
87+
return str->s ? ZSTR_LEN(str->s) : 0;
88+
}
89+
90+
static zend_always_inline zend_string *smart_str_extract(smart_str *str) {
91+
if (str->s) {
92+
zend_string *res;
93+
smart_str_0(str);
94+
res = str->s;
95+
str->s = NULL;
96+
return res;
97+
} else {
98+
return ZSTR_EMPTY_ALLOC();
99+
}
100+
}
101+
83102
static zend_always_inline void smart_str_appendc_ex(smart_str *dest, char ch, zend_bool persistent) {
84103
size_t new_len = smart_str_alloc(dest, 1, persistent);
85104
ZSTR_VAL(dest->s)[new_len - 1] = ch;

Zend/zend_smart_string.h

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP Version 7 |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 1997-2016 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| [email protected] so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Author: Sascha Schumann <[email protected]> |
16+
| Xinchen Hui <[email protected]> |
17+
+----------------------------------------------------------------------+
18+
*/
19+
20+
/* $Id$ */
21+
22+
#ifndef PHP_SMART_STRING_H
23+
#define PHP_SMART_STRING_H
24+
25+
#include "zend_smart_string_public.h"
26+
27+
#include <stdlib.h>
28+
#ifndef SMART_STR_USE_REALLOC
29+
#include <zend.h>
30+
#endif
31+
32+
#ifndef SMART_STRING_PREALLOC
33+
#define SMART_STRING_PREALLOC 128
34+
#endif
35+
36+
#ifndef SMART_STRING_START_SIZE
37+
#define SMART_STRING_START_SIZE 78
38+
#endif
39+
40+
#ifdef SMART_STRING_USE_REALLOC
41+
#define SMART_STRING_REALLOC(a,b,c) realloc((a),(b))
42+
#else
43+
#define SMART_STRING_REALLOC(a,b,c) perealloc((a),(b),(c))
44+
#endif
45+
46+
#define SMART_STRING_DO_REALLOC(d, what) \
47+
(d)->c = SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what))
48+
49+
/* wrapper */
50+
51+
#define smart_string_appends_ex(str, src, what) \
52+
smart_string_appendl_ex((str), (src), strlen(src), (what))
53+
#define smart_string_appends(str, src) \
54+
smart_string_appendl((str), (src), strlen(src))
55+
#define smart_string_append_ex(str, src, what) \
56+
smart_string_appendl_ex((str), ((smart_string *)(src))->c, \
57+
((smart_string *)(src))->len, (what));
58+
#define smart_string_sets(str, src) \
59+
smart_string_setl((str), (src), strlen(src));
60+
61+
#define smart_string_appendc(str, c) \
62+
smart_string_appendc_ex((str), (c), 0)
63+
#define smart_string_free(s) \
64+
smart_string_free_ex((s), 0)
65+
#define smart_string_appendl(str, src, len) \
66+
smart_string_appendl_ex((str), (src), (len), 0)
67+
#define smart_string_append(str, src) \
68+
smart_string_append_ex((str), (src), 0)
69+
#define smart_string_append_long(str, val) \
70+
smart_string_append_long_ex((str), (val), 0)
71+
#define smart_string_append_unsigned(str, val) \
72+
smart_string_append_unsigned_ex((str), (val), 0)
73+
74+
static zend_always_inline size_t smart_string_alloc(smart_string *str, size_t len, zend_bool persistent) {
75+
if (!str->c) {
76+
str->len = 0;
77+
str->a = len < SMART_STRING_START_SIZE
78+
? SMART_STRING_START_SIZE
79+
: len + SMART_STRING_PREALLOC;
80+
SMART_STRING_DO_REALLOC(str, persistent);
81+
return len;
82+
} else {
83+
if (UNEXPECTED((size_t) len > SIZE_MAX - str->len)) {
84+
zend_error(E_ERROR, "String size overflow");
85+
}
86+
len += str->len;
87+
if (UNEXPECTED(len >= str->a)) {
88+
str->a = len + SMART_STRING_PREALLOC;
89+
SMART_STRING_DO_REALLOC(str, persistent);
90+
}
91+
}
92+
return len;
93+
}
94+
95+
static zend_always_inline void smart_string_free_ex(smart_string *str, zend_bool persistent) {
96+
if (str->c) {
97+
pefree(str->c, persistent);
98+
str->c = NULL;
99+
}
100+
str->a = str->len = 0;
101+
}
102+
103+
static zend_always_inline void smart_string_0(smart_string *str) {
104+
if (str->c) {
105+
str->c[str->len] = '\0';
106+
}
107+
}
108+
109+
static zend_always_inline void smart_string_appendc_ex(smart_string *dest, char ch, zend_bool persistent) {
110+
dest->len = smart_string_alloc(dest, 1, persistent);
111+
dest->c[dest->len - 1] = ch;
112+
}
113+
114+
static zend_always_inline void smart_string_appendl_ex(smart_string *dest, const char *str, size_t len, zend_bool persistent) {
115+
size_t new_len = smart_string_alloc(dest, len, persistent);
116+
memcpy(dest->c + dest->len, str, len);
117+
dest->len = new_len;
118+
119+
}
120+
121+
static zend_always_inline void smart_string_append_long_ex(smart_string *dest, zend_long num, zend_bool persistent) {
122+
char buf[32];
123+
char *result = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
124+
smart_string_appendl_ex(dest, result, buf + sizeof(buf) - 1 - result, persistent);
125+
}
126+
127+
static zend_always_inline void smart_string_append_unsigned_ex(smart_string *dest, zend_ulong num, zend_bool persistent) {
128+
char buf[32];
129+
char *result = zend_print_ulong_to_buf(buf + sizeof(buf) - 1, num);
130+
smart_string_appendl_ex(dest, result, buf + sizeof(buf) - 1 - result, persistent);
131+
}
132+
133+
static zend_always_inline void smart_string_setl(smart_string *dest, char *src, size_t len) {
134+
dest->len = len;
135+
dest->a = len + 1;
136+
dest->c = src;
137+
}
138+
139+
#endif

0 commit comments

Comments
 (0)