Skip to content

fix: used allocation without checking #9015

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: PHP-8.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Zend/zend_constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void clean_module_constants(int module_number)

void zend_startup_constants(void)
{
EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
EG(zend_constants) = (HashTable *) pemalloc(sizeof(HashTable), 1);
zend_hash_init(EG(zend_constants), 128, NULL, ZEND_CONSTANT_DTOR, 1);
}

Expand Down Expand Up @@ -145,7 +145,7 @@ void zend_register_standard_constants(void)
void zend_shutdown_constants(void)
{
zend_hash_destroy(EG(zend_constants));
free(EG(zend_constants));
pefree(EG(zend_constants), 1);
}

ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number)
Expand Down
4 changes: 2 additions & 2 deletions ext/dom/php_dom.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,14 +511,14 @@ static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */
static void dom_copy_prop_handler(zval *zv) /* {{{ */
{
dom_prop_handler *hnd = Z_PTR_P(zv);
Z_PTR_P(zv) = malloc(sizeof(dom_prop_handler));
Z_PTR_P(zv) = pemalloc(sizeof(dom_prop_handler), 1);
memcpy(Z_PTR_P(zv), hnd, sizeof(dom_prop_handler));
}
/* }}} */

static void dom_dtor_prop_handler(zval *zv) /* {{{ */
{
free(Z_PTR_P(zv));
pefree(Z_PTR_P(zv), 1);
}

static const zend_module_dep dom_deps[] = {
Expand Down
8 changes: 4 additions & 4 deletions ext/exif/exif.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ PHP_MSHUTDOWN_FUNCTION(exif)
UNREGISTER_INI_ENTRIES();
if (EXIF_G(tag_table_cache)) {
zend_hash_destroy(EXIF_G(tag_table_cache));
free(EXIF_G(tag_table_cache));
pefree(EXIF_G(tag_table_cache), 1);
}
return SUCCESS;
}
Expand Down Expand Up @@ -1306,7 +1306,7 @@ static const maker_note_type maker_note_array[] = {

static HashTable *exif_make_tag_ht(tag_info_type *tag_table)
{
HashTable *ht = malloc(sizeof(HashTable));
HashTable *ht = pemalloc(sizeof(HashTable), 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be persistent. ht is later stored in EXIF_G(tag_table_cache) which lives beyond requests, as far as I can see.

zend_hash_init(ht, 0, NULL, NULL, 1);
while (tag_table->Tag != TAG_END_OF_LIST) {
if (!zend_hash_index_add_ptr(ht, tag_table->Tag, tag_table->Desc)) {
Expand All @@ -1321,15 +1321,15 @@ static void exif_tag_ht_dtor(zval *zv)
{
HashTable *ht = Z_PTR_P(zv);
zend_hash_destroy(ht);
free(ht);
pefree(ht, 0);
}

static HashTable *exif_get_tag_ht(tag_info_type *tag_table)
{
HashTable *ht;

if (!EXIF_G(tag_table_cache)) {
EXIF_G(tag_table_cache) = malloc(sizeof(HashTable));
EXIF_G(tag_table_cache) = pemalloc(sizeof(HashTable), 1);
zend_hash_init(EXIF_G(tag_table_cache), 0, NULL, exif_tag_ht_dtor, 1);
}

Expand Down
8 changes: 4 additions & 4 deletions ext/ffi/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2335,7 +2335,7 @@ static void zend_ffi_scope_hash_dtor(zval *zv) /* {{{ */
zend_hash_destroy(scope->tags);
free(scope->tags);
}
free(scope);
pefree(scope, 1);
}
/* }}} */

Expand Down Expand Up @@ -3333,12 +3333,12 @@ static zend_ffi *zend_ffi_load(const char *filename, zend_bool preload) /* {{{ *
}

if (!scope) {
scope = malloc(sizeof(zend_ffi_scope));
scope = pemalloc(sizeof(zend_ffi_scope), 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might need to mirror it in their freeing counterparts.

scope->symbols = FFI_G(symbols);
scope->tags = FFI_G(tags);

if (!FFI_G(scopes)) {
FFI_G(scopes) = malloc(sizeof(HashTable));
FFI_G(scopes) = pemalloc(sizeof(HashTable), 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

zend_hash_init(FFI_G(scopes), 0, NULL, zend_ffi_scope_hash_dtor, 1);
}

Expand Down Expand Up @@ -5215,7 +5215,7 @@ static ZEND_GSHUTDOWN_FUNCTION(ffi)
{
if (ffi_globals->scopes) {
zend_hash_destroy(ffi_globals->scopes);
free(ffi_globals->scopes);
pefree(ffi_globals->scopes, 1);
}
zend_hash_destroy(&ffi_globals->types);
}
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/zend_shared_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ void zend_shared_alloc_shutdown(void)
smm_shared_globals = &tmp_shared_globals;
shared_segments_array_size = ZSMMG(shared_segments_count) * (S_H(segment_type_size)() + sizeof(void *));
if (shared_segments_array_size > 16) {
tmp_shared_segments = malloc(shared_segments_array_size);
tmp_shared_segments = pemalloc(shared_segments_array_size, 1);
} else {
tmp_shared_segments = shared_segments_buf;
}
Expand All @@ -296,7 +296,7 @@ void zend_shared_alloc_shutdown(void)
S_H(detach_segment)(ZSMMG(shared_segments)[i]);
}
if (shared_segments_array_size > 16) {
free(ZSMMG(shared_segments));
pefree(ZSMMG(shared_segments), 1);
}
ZSMMG(shared_segments) = NULL;
g_shared_alloc_handler = NULL;
Expand Down
75 changes: 20 additions & 55 deletions main/fastcgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ static void fcgi_hash_init(fcgi_hash *h)
{
memset(h->hash_table, 0, sizeof(h->hash_table));
h->list = NULL;
h->buckets = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
h->buckets = (fcgi_hash_buckets*)pemalloc(sizeof(fcgi_hash_buckets), 1);
h->buckets->idx = 0;
h->buckets->next = NULL;
h->data = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + FCGI_HASH_SEG_SIZE);
h->data = (fcgi_data_seg*)pemalloc(sizeof(fcgi_data_seg) - 1 + FCGI_HASH_SEG_SIZE, 1);
h->data->pos = h->data->data;
h->data->end = h->data->pos + FCGI_HASH_SEG_SIZE;
h->data->next = NULL;
Expand All @@ -273,13 +273,13 @@ static void fcgi_hash_destroy(fcgi_hash *h)
while (b) {
fcgi_hash_buckets *q = b;
b = b->next;
free(q);
pefree(q, 1);
}
p = h->data;
while (p) {
fcgi_data_seg *q = p;
p = p->next;
free(q);
pefree(q, 1);
}
}

Expand All @@ -292,15 +292,15 @@ static void fcgi_hash_clean(fcgi_hash *h)
fcgi_hash_buckets *q = h->buckets;

h->buckets = h->buckets->next;
free(q);
pefree(q, 1);
}
h->buckets->idx = 0;
/* delete all data segments except the first one */
while (h->data->next) {
fcgi_data_seg *q = h->data;

h->data = h->data->next;
free(q);
pefree(q, 1);
}
h->data->pos = h->data->data;
}
Expand All @@ -311,7 +311,7 @@ static inline char* fcgi_hash_strndup(fcgi_hash *h, char *str, unsigned int str_

if (UNEXPECTED(h->data->pos + str_len + 1 >= h->data->end)) {
unsigned int seg_size = (str_len + 1 > FCGI_HASH_SEG_SIZE) ? str_len + 1 : FCGI_HASH_SEG_SIZE;
fcgi_data_seg *p = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + seg_size);
fcgi_data_seg *p = (fcgi_data_seg*)pemalloc(sizeof(fcgi_data_seg) - 1 + seg_size, 1);

p->pos = p->data;
p->end = p->pos + seg_size;
Expand Down Expand Up @@ -343,7 +343,7 @@ static char* fcgi_hash_set(fcgi_hash *h, unsigned int hash_value, char *var, uns
}

if (UNEXPECTED(h->buckets->idx >= FCGI_HASH_TABLE_SIZE)) {
fcgi_hash_buckets *b = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
fcgi_hash_buckets *b = (fcgi_hash_buckets*)pemalloc(sizeof(fcgi_hash_buckets), 1);
b->idx = 0;
b->next = h->buckets;
h->buckets = b;
Expand Down Expand Up @@ -561,7 +561,8 @@ void fcgi_shutdown(void)
}
is_fastcgi = 0;
if (allowed_clients) {
free(allowed_clients);
pefree(allowed_clients, 1);
allowed_clients = NULL;
}
}

Expand Down Expand Up @@ -769,45 +770,9 @@ int fcgi_listen(const char *path, int backlog)
chmod(path, 0777);
} else {
char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
char *cur, *end;
int n;

if (ip) {
ip = strdup(ip);
cur = ip;
n = 0;
while (*cur) {
if (*cur == ',') n++;
cur++;
}
allowed_clients = malloc(sizeof(sa_t) * (n+2));
n = 0;
cur = ip;
while (cur) {
end = strchr(cur, ',');
if (end) {
*end = 0;
end++;
}
if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
allowed_clients[n].sa.sa_family = AF_INET;
n++;
#ifdef HAVE_IPV6
} else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
allowed_clients[n].sa.sa_family = AF_INET6;
n++;
#endif
} else {
fcgi_log(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
}
cur = end;
}
allowed_clients[n].sa.sa_family = 0;
free(ip);
if (!n) {
fcgi_log(FCGI_ERROR, "There are no allowed addresses");
/* don't clear allowed_clients as it will create an "open for all" security issue */
}
fcgi_set_allowed_clients(ip);
}
}

Expand All @@ -826,23 +791,23 @@ int fcgi_listen(const char *path, int backlog)
return listen_socket;
}

void fcgi_set_allowed_clients(char *ip)
void fcgi_set_allowed_clients(const char *ip)
{
char *cur, *end;
int n;

if (ip) {
ip = strdup(ip);
cur = ip;
char *dup_ip = estrdup(ip);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can see this functions is called from fpm_php_init_child which is called indirectly from main outside of request context. I guess this should work fine if the allocator is started, I'm not sure which one is preferable.

cur = dup_ip;
n = 0;
while (*cur) {
if (*cur == ',') n++;
cur++;
}
if (allowed_clients) free(allowed_clients);
allowed_clients = malloc(sizeof(sa_t) * (n+2));
if (allowed_clients) pefree(allowed_clients, 1);
allowed_clients = safe_pemalloc(sizeof(sa_t), n+2, 0, 1);
n = 0;
cur = ip;
cur = dup_ip;
while (cur) {
end = strchr(cur, ',');
if (end) {
Expand All @@ -863,7 +828,7 @@ void fcgi_set_allowed_clients(char *ip)
cur = end;
}
allowed_clients[n].sa.sa_family = 0;
free(ip);
efree(dup_ip);
if (!n) {
fcgi_log(FCGI_ERROR, "There are no allowed addresses");
/* don't clear allowed_clients as it will create an "open for all" security issue */
Expand All @@ -877,7 +842,7 @@ static void fcgi_hook_dummy() {

fcgi_request *fcgi_init_request(int listen_socket, void(*on_accept)(), void(*on_read)(), void(*on_close)())
{
fcgi_request *req = calloc(1, sizeof(fcgi_request));
fcgi_request *req = pecalloc(1, sizeof(fcgi_request), 1);
req->listen_socket = listen_socket;
req->fd = -1;
req->id = -1;
Expand Down Expand Up @@ -912,7 +877,7 @@ fcgi_request *fcgi_init_request(int listen_socket, void(*on_accept)(), void(*on_

void fcgi_destroy_request(fcgi_request *req) {
fcgi_hash_destroy(&req->env);
free(req);
pefree(req, 1);
}

static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
Expand Down
2 changes: 1 addition & 1 deletion main/fastcgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void fcgi_terminate(void);
int fcgi_listen(const char *path, int backlog);
fcgi_request* fcgi_init_request(int listen_socket, void(*on_accept)(), void(*on_read)(), void(*on_close)());
void fcgi_destroy_request(fcgi_request *req);
void fcgi_set_allowed_clients(char *ip);
void fcgi_set_allowed_clients(const char *ip);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
const char *fcgi_get_last_client_ip();
Expand Down
15 changes: 8 additions & 7 deletions sapi/cgi/cgi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,12 +758,12 @@ static void sapi_cgi_log_message(const char *message, int syslog_type_int)
request = (fcgi_request*) SG(server_context);
if (request) {
int ret, len = (int)strlen(message);
char *buf = malloc(len+2);

char *buf = pemalloc(len+2, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this can be called outside of request context.

memcpy(buf, message, len);
memcpy(buf + len, "\n", sizeof("\n"));
ret = fcgi_write(request, FCGI_STDERR, buf, (int)(len + 1));
free(buf);
pefree(buf, 0);
if (ret < 0) {
php_handle_aborted_connection();
}
Expand Down Expand Up @@ -1801,15 +1801,16 @@ int main(int argc, char *argv[])
if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
/* we've got query string that has no = - apache CGI will pass it to command line */
unsigned char *p;
decoded_query_string = strdup(query_string);

decoded_query_string = pestrdup(query_string, 0);
php_url_decode(decoded_query_string, strlen(decoded_query_string));
for (p = (unsigned char *)decoded_query_string; *p && *p <= ' '; p++) {
/* skip all leading spaces */
}
if(*p == '-') {
skip_getopt = 1;
}
free(decoded_query_string);
pefree(decoded_query_string, 0);
}

while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
Expand Down Expand Up @@ -2438,7 +2439,7 @@ consult the installation file that came with this distribution, or visit \n\
}

len += 2;
s = malloc(len);
s = pemalloc(len, 0);
*s = '\0'; /* we are pretending it came from the environment */
for (i = php_optind; i < argc; i++) {
strlcat(s, argv[i], len);
Expand Down Expand Up @@ -2507,7 +2508,7 @@ consult the installation file that came with this distribution, or visit \n\
}

if (free_query_string && SG(request_info).query_string) {
free(SG(request_info).query_string);
pefree(SG(request_info).query_string, 0);
SG(request_info).query_string = NULL;
}

Expand Down