Skip to content

Fix memory leaks in ext/tidy basedir restriction code #15046

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

Conversation

nielsdos
Copy link
Member

TIDY_APPLY_CONFIG can early return because it's a macro, but then the cleanup paths are not executed. Transform this to a real function and handle the cleanups correctly at the callsites.

This was detected using an experimental static analyser I'm developing.

TIDY_APPLY_CONFIG can early return because it's a macro, but then the
cleanup paths are not executed. Transform this to a real function and
handle the cleanups correctly at the callsites.
if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht) != SUCCESS) {
/* TODO: this is the constructor, we should throw probably... */
zend_string_release_ex(contents, 0);
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.

not sure about this indeed.

Copy link
Member Author

Choose a reason for hiding this comment

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

This keeps the existing behaviour of calling ->__construct(...) manually, and yes it returns false in that case. Constructors don't necessarily have a void return :(
I believe this should be at least fixed for master by throwing an exception instead. cc @Girgias

Copy link
Member

Choose a reason for hiding this comment

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

Yes this should, especially if the constructor can emit a warning

Copy link
Member

@devnexen devnexen left a comment

Choose a reason for hiding this comment

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

makes sense otherwise

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.

Minor nits and suggestions for follow-up PRs

Comment on lines +213 to +220
if (ht_options) {
return _php_tidy_apply_config_array(doc, ht_options);
} else if (str_string) {
if (php_check_open_basedir(ZSTR_VAL(str_string))) {
return FAILURE;
}
php_tidy_load_config(doc, ZSTR_VAL(str_string));
}
Copy link
Member

Choose a reason for hiding this comment

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

Note to myself, see if the HashTable and underlying char pointer can be made const.

Comment on lines +1027 to +1028
if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht) != SUCCESS
|| php_tidy_parse_string(obj, ZSTR_VAL(input), (uint32_t)ZSTR_LEN(input), enc) == FAILURE) {
Copy link
Member

Choose a reason for hiding this comment

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

Why is one != SUCCESS and the other one is == FAILURE? I think it would be better if both use the same comparison check.

Comment on lines +1095 to +1096
if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht) != SUCCESS
|| php_tidy_parse_string(obj, ZSTR_VAL(contents), (uint32_t)ZSTR_LEN(contents), enc) == FAILURE) {
Copy link
Member

Choose a reason for hiding this comment

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

Ditto

if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht) != SUCCESS) {
/* TODO: this is the constructor, we should throw probably... */
zend_string_release_ex(contents, 0);
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.

Yes this should, especially if the constructor can emit a warning

Comment on lines +1432 to +1433
if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht) != SUCCESS
|| php_tidy_parse_string(obj, ZSTR_VAL(contents), (uint32_t)ZSTR_LEN(contents), enc) == FAILURE) {
Copy link
Member

Choose a reason for hiding this comment

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

Ditto

Copy link
Member

Choose a reason for hiding this comment

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

Also not for a follow-up PR that this could use RETVAL_BOOL()

Comment on lines +1465 to 1468
if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht) == SUCCESS
&& php_tidy_parse_string(obj, ZSTR_VAL(input), (uint32_t)ZSTR_LEN(input), enc) == SUCCESS) {
RETURN_TRUE;
}
Copy link
Member

Choose a reason for hiding this comment

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

Note for a follow-up PR, this could just use a RETURN_BOOL()

Comment on lines +40 to +42
=== __construct ===

Warning: tidy::__construct(): open_basedir restriction in effect. File(my_config_file.ini) is not within the allowed path(s): (%sopen_basedir) in %s on line %d
Copy link
Member

Choose a reason for hiding this comment

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

This definitely needs to be addressed in master, as constructors must always throw an exception when they fail.

@nielsdos
Copy link
Member Author

Ok I am gonna merge this and make a follow-up for master. Thanks for the input.

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