Skip to content

ext/session refactoring: INI settings #16419

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 10 commits into
base: master
Choose a base branch
from

Conversation

jorgsowa
Copy link
Contributor

Rebase of PR: #9322

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this again! I still don't understand why I needed to duplicate some of the strings, maybe @nielsdos has an idea?

return false;
}
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
if (strpbrk(ZSTR_VAL(name), "=,; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
Copy link
Member

Choose a reason for hiding this comment

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

I know this is an existing issue but \013 is a vertical tab (\v) and \014 is a form feed (\f) which would probably be clearer than needed to look up some documentation

Comment on lines +1381 to +1408
// TODO Use zend_string_cmp API?
if (!strcasecmp(lim->name, ZSTR_VAL(PS(cache_limiter)))) {
Copy link
Member

Choose a reason for hiding this comment

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

Annoyingly we don't have a zend_string_equals_cstr_ci() API.

Comment on lines +1411 to 1440
spprintf(&session_cookie, 0, "Set-Cookie: %s=", ZSTR_VAL(PS(session_name)));

// TODO Manually compute from known information?
session_cookie_len = strlen(session_cookie);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe using the strpprintf API to generate a zend_string is better here?

Copy link
Member

Choose a reason for hiding this comment

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

Generate a zend_string here.

@nielsdos
Copy link
Member

nielsdos commented Oct 14, 2024

I still don't understand why I needed to duplicate some of the strings, maybe @nielsdos has an idea?

@Girgias This is because the strings are persistent, but don't have GC_PERSISTENT_LOCAL set. If you're on a multithreaded SAPI/ZTS, then sharing the same non-interned persistent strings can cause race conditions when changing the refcounts. If GC_PERSISTENT_LOCAL is set this check is skipped because you're saying to the engine that these strings are local to the current thread, and thus the reference counts cannot be racy. (Make sure you only do this if you're certain that these strings are not shared across threads). In this particular case, the strings come from INI settings, and I haven't checked if they are local to the current thread, but my gut feeling says they're shared across threads.

@Girgias
Copy link
Member

Girgias commented Oct 15, 2024

I still don't understand why I needed to duplicate some of the strings, maybe @nielsdos has an idea?

@Girgias This is because the strings are persistent, but don't have GC_PERSISTENT_LOCAL set. If you're on a multithreaded SAPI/ZTS, then sharing the same non-interned persistent strings can cause race conditions when changing the refcounts. If GC_PERSISTENT_LOCAL is set this check is skipped because you're saying to the engine that these strings are local to the current thread, and thus the reference counts cannot be racy. (Make sure you only do this if you're certain that these strings are not shared across threads). In this particular case, the strings come from INI settings, and I haven't checked if they are local to the current thread, but my gut feeling says they're shared across threads.

Hum, I suppose the default value of the INI setting might be shared across threads, but I don't know about overwritten values 🤔

@jorgsowa jorgsowa force-pushed the session-ext-improvements branch from db5e63a to 07dbb54 Compare December 6, 2024 00:10
Girgias and others added 10 commits January 10, 2025 19:45
However, the code is somewhat disgusting as I'm hitting
Zend/zend_types.h:1222: zend_gc_delref: Assertion (zval_gc_flags((p)->u.type_info) & ((1<<7)|(1<<8))) != (1<<7) failed.
Failures that I don't understand.
Also fixed a bug where nul bytes where not properly checked
Co-authored-by: Tim Düsterhus <timwolla@googlemail.com>
@jorgsowa jorgsowa force-pushed the session-ext-improvements branch from 07dbb54 to d5de6ed Compare January 10, 2025 18:45
@jorgsowa
Copy link
Contributor Author

I fixed failing tests on ZTS by changing OnUpdateString to

	zend_string **p = (zend_string **) ZEND_INI_GET_ADDR();
	*p = new_value ? new_value : NULL;
	return SUCCESS;

I'm not quite sure why it was failing though. Anyways, now everything seems to pass.

@jorgsowa jorgsowa requested a review from Girgias January 10, 2025 19:17
Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

Do we still need the duplication?

Comment on lines +727 to +732
if (strpbrk(ZSTR_VAL(name), "=,; \t\r\n\v\f") != NULL) { /* man isspace for \v and \f */
if (diagnostic_type) {
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" must not contain any of the following "
"'=,; \\t\\r\\n\\v\\f'", ZSTR_VAL(name));
}
return false;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (strpbrk(ZSTR_VAL(name), "=,; \t\r\n\v\f") != NULL) { /* man isspace for \v and \f */
if (diagnostic_type) {
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" must not contain any of the following "
"'=,; \\t\\r\\n\\v\\f'", ZSTR_VAL(name));
}
return false;
if (strpbrk(ZSTR_VAL(name), SESSION_FORBIDDEN_CHARS) != NULL) { /* man isspace for \v and \f */
if (diagnostic_type) {
php_error_docref(NULL, diagnostic_type, "session.name \"%s\" must not contain any of the following \""
SESSION_FORBIDDEN_CHARS "\"", ZSTR_VAL(name));
}
return false;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants