Skip to content

sapi/*: move duplicate "--define" code to library #8241

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,7 @@ PHP_ADD_SOURCES(TSRM, TSRM.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)

PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \
fopen_wrappers.c alloca.c php_scandir.c \
php_ini_builder.c \
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \
network.c php_open_temporary_file.c \
Expand Down
82 changes: 82 additions & 0 deletions main/php_ini_builder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Max Kellermann <max.kellermann@ionos.com> |
+----------------------------------------------------------------------+
*/

#include "php_ini_builder.h"

#include <ctype.h>
#include <string.h>

PHPAPI void php_ini_builder_prepend(struct php_ini_builder *b, const char *src, size_t length)
{
php_ini_builder_realloc(b, length);
if (b->length > 0)
memmove(b->value + length, b->value, b->length);
Comment on lines +25 to +26
Copy link
Member

Choose a reason for hiding this comment

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

Maybe use explicit {} for the if block?

Copy link
Member

Choose a reason for hiding this comment

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

AFAIK we don't have any guidelines on this. I'm fine with making braces mandatory for new code but I think the risks of not adding braces are largely overblown.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think it's a risk, just confusing IMHO (at least I get confused)

Copy link
Member

Choose a reason for hiding this comment

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

The argument is usually somebody might extend the block in the if and forget that braces are missing.

 if (foo())
     bar();
+    baz();

Or bar() might be a macro containing multiple statements but we use do {} while (0) in our macros to prevent that.

Copy link
Member

Choose a reason for hiding this comment

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

@iluuu1994 just FYI we actually have guidelines on this:

php-src/CODING_STANDARDS.md

Lines 243 to 258 in 31692a1

3. Be generous with whitespace and braces. Keep one empty line between the
variable declaration section and the statements in a block, as well as
between logical statement groups in a block. Maintain at least one empty
line between two functions, preferably two. Always prefer:
```c
if (foo) {
bar;
}
```
to:
```c
if(foo)bar;
```

Copy link
Member

Choose a reason for hiding this comment

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

@bukka Ah, good to know.

memcpy(b->value, src, length);
b->length += length;
}

PHPAPI void php_ini_builder_unquoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length)
{
php_ini_builder_realloc(b, name_length + 1 + value_length + 1);

memcpy(b->value + b->length, name, name_length);
b->length += name_length;

b->value[b->length++] = '=';

memcpy(b->value + b->length, value, value_length);
b->length += value_length;

b->value[b->length++] = '\n';
}

PHPAPI void php_ini_builder_quoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length)
{
php_ini_builder_realloc(b, name_length + 2 + value_length + 2);

memcpy(b->value + b->length, name, name_length);
b->length += name_length;

b->value[b->length++] = '=';
b->value[b->length++] = '"';

memcpy(b->value + b->length, value, value_length);
b->length += value_length;

b->value[b->length++] = '"';
b->value[b->length++] = '\n';
}

PHPAPI void php_ini_builder_define(struct php_ini_builder *b, const char *arg)
{
const size_t len = strlen(arg);
const char *val = strchr(arg, '=');

if (val != NULL) {
val++;
if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
php_ini_builder_quoted(b, arg, val - arg - 1, val, arg + len - val);
} else {
php_ini_builder_realloc(b, len + strlen("\n"));
memcpy(b->value + b->length, arg, len);
b->length += len;
b->value[b->length++] = '\n';
}
} else {
php_ini_builder_unquoted(b, arg, len, "1", 1);
}
}

95 changes: 95 additions & 0 deletions main/php_ini_builder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Max Kellermann <max.kellermann@ionos.com> |
+----------------------------------------------------------------------+
*/

#ifndef PHP_INI_BUILDER_H
#define PHP_INI_BUILDER_H

#include "php.h"

/**
* A class which helps with constructing INI entries from the command
* line.
*/
struct php_ini_builder {
char *value;
size_t length;
};

BEGIN_EXTERN_C()

static inline void php_ini_builder_init(struct php_ini_builder *b)
{
b->value = NULL;
b->length = 0;
}

static inline void php_ini_builder_deinit(struct php_ini_builder *b)
{
free(b->value);
}

/**
* Null-terminate the buffer and return it.
*/
static inline char *php_ini_builder_finish(struct php_ini_builder *b)
{
if (b->value != NULL) {
/* null-terminate the string */
b->value[b->length] = '\0';
}

return b->value;
}

/**
* Make room for more data.
*
* @param delta the number of bytes to be appended
*/
static inline void php_ini_builder_realloc(struct php_ini_builder *b, size_t delta)
{
/* reserve enough space for the null terminator */
b->value = realloc(b->value, b->length + delta + 1);
}

/**
* Prepend a string.
*
* @param src the source string
* @param length the size of the source string
*/
PHPAPI void php_ini_builder_prepend(struct php_ini_builder *b, const char *src, size_t length);

#define php_ini_builder_prepend_literal(b, l) php_ini_builder_prepend(b, l, strlen(l))

/**
* Append an unquoted name/value pair.
*/
PHPAPI void php_ini_builder_unquoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length);

/**
* Append a quoted name/value pair.
*/
PHPAPI void php_ini_builder_quoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length);

/**
* Parse an INI entry from the command-line option "--define".
*/
PHPAPI void php_ini_builder_define(struct php_ini_builder *b, const char *arg);

END_EXTERN_C()

#endif
42 changes: 9 additions & 33 deletions sapi/cgi/cgi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "php.h"
#include "php_globals.h"
#include "php_variables.h"
#include "php_ini_builder.h"
#include "zend_modules.h"

#include "SAPI.h"
Expand Down Expand Up @@ -1727,7 +1728,7 @@ int main(int argc, char *argv[])
int orig_optind = php_optind;
char *orig_optarg = php_optarg;
char *script_file = NULL;
size_t ini_entries_len = 0;
struct php_ini_builder ini_builder;
/* end of temporary locals */

int max_requests = 500;
Expand Down Expand Up @@ -1812,6 +1813,8 @@ int main(int argc, char *argv[])
free(decoded_query_string);
}

php_ini_builder_init(&ini_builder);

while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
switch (c) {
case 'c':
Expand All @@ -1823,37 +1826,10 @@ int main(int argc, char *argv[])
case 'n':
cgi_sapi_module.php_ini_ignore = 1;
break;
case 'd': {
case 'd':
/* define ini entries on command line */
size_t len = strlen(php_optarg);
char *val;

if ((val = strchr(php_optarg, '='))) {
val++;
if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
ini_entries_len += (val - php_optarg);
memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1);
ini_entries_len++;
memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
ini_entries_len += len - (val - php_optarg);
memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
ini_entries_len += sizeof("\n\0\"") - 2;
} else {
cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
ini_entries_len += len + sizeof("\n\0") - 2;
}
} else {
cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
ini_entries_len += len + sizeof("=1\n\0") - 2;
}
php_ini_builder_define(&ini_builder, php_optarg);
break;
}
/* if we're started on command line, check to see if
* we are being started as an 'external' fastcgi
* server by accepting a bindpath parameter. */
Expand All @@ -1870,6 +1846,8 @@ int main(int argc, char *argv[])
php_optind = orig_optind;
php_optarg = orig_optarg;

cgi_sapi_module.ini_entries = php_ini_builder_finish(&ini_builder);

if (fastcgi || bindpath) {
/* Override SAPI callbacks */
cgi_sapi_module.ub_write = sapi_fcgi_ub_write;
Expand Down Expand Up @@ -2619,9 +2597,7 @@ consult the installation file that came with this distribution, or visit \n\
if (cgi_sapi_module.php_ini_path_override) {
free(cgi_sapi_module.php_ini_path_override);
}
if (cgi_sapi_module.ini_entries) {
free(cgi_sapi_module.ini_entries);
}
php_ini_builder_deinit(&ini_builder);
} zend_catch {
exit_status = 255;
} zend_end_try();
Expand Down
55 changes: 10 additions & 45 deletions sapi/cli/php_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "php.h"
#include "php_globals.h"
#include "php_variables.h"
#include "php_ini_builder.h"
#include "zend_hash.h"
#include "zend_modules.h"
#include "zend_interfaces.h"
Expand Down Expand Up @@ -131,7 +132,7 @@ const char HARDCODED_INI[] =
"implicit_flush=1\n"
"output_buffering=0\n"
"max_execution_time=0\n"
"max_input_time=-1\n\0";
"max_input_time=-1\n";


const opt_struct OPTIONS[] = {
Expand Down Expand Up @@ -1176,8 +1177,7 @@ int main(int argc, char *argv[])
char *php_optarg = NULL;
int php_optind = 1, use_extended_info = 0;
char *ini_path_override = NULL;
char *ini_entries = NULL;
size_t ini_entries_len = 0;
struct php_ini_builder ini_builder;
int ini_ignore = 0;
sapi_module_struct *sapi_module = &cli_sapi_module;

Expand Down Expand Up @@ -1239,6 +1239,8 @@ int main(int argc, char *argv[])
setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
#endif

php_ini_builder_init(&ini_builder);

while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2))!=-1) {
switch (c) {
case 'c':
Expand All @@ -1250,37 +1252,10 @@ int main(int argc, char *argv[])
case 'n':
ini_ignore = 1;
break;
case 'd': {
case 'd':
/* define ini entries on command line */
size_t len = strlen(php_optarg);
char *val;

if ((val = strchr(php_optarg, '='))) {
val++;
if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
ini_entries_len += (val - php_optarg);
memcpy(ini_entries + ini_entries_len, "\"", 1);
ini_entries_len++;
memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg));
ini_entries_len += len - (val - php_optarg);
memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
ini_entries_len += sizeof("\n\0\"") - 2;
} else {
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\n\0"));
memcpy(ini_entries + ini_entries_len, php_optarg, len);
memcpy(ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
ini_entries_len += len + sizeof("\n\0") - 2;
}
} else {
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
memcpy(ini_entries + ini_entries_len, php_optarg, len);
memcpy(ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
ini_entries_len += len + sizeof("=1\n\0") - 2;
}
php_ini_builder_define(&ini_builder, php_optarg);
break;
}
#ifndef PHP_CLI_WIN32_NO_CONSOLE
case 'S':
sapi_module = &cli_server_sapi_module;
Expand Down Expand Up @@ -1317,18 +1292,10 @@ int main(int argc, char *argv[])
sapi_module->executable_location = argv[0];

if (sapi_module == &cli_sapi_module) {
if (ini_entries) {
ini_entries = realloc(ini_entries, ini_entries_len + sizeof(HARDCODED_INI));
memmove(ini_entries + sizeof(HARDCODED_INI) - 2, ini_entries, ini_entries_len + 1);
memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI) - 2);
} else {
ini_entries = malloc(sizeof(HARDCODED_INI));
memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI));
}
ini_entries_len += sizeof(HARDCODED_INI) - 2;
php_ini_builder_prepend_literal(&ini_builder, HARDCODED_INI);
}

sapi_module->ini_entries = ini_entries;
sapi_module->ini_entries = php_ini_builder_finish(&ini_builder);

/* startup after we get the above ini override se we get things right */
if (sapi_module->startup(sapi_module) == FAILURE) {
Expand Down Expand Up @@ -1375,9 +1342,7 @@ int main(int argc, char *argv[])
if (ini_path_override) {
free(ini_path_override);
}
if (ini_entries) {
free(ini_entries);
}
php_ini_builder_deinit(&ini_builder);
if (module_started) {
php_module_shutdown();
}
Expand Down
Loading