Skip to content
Merged
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
36 changes: 25 additions & 11 deletions runtime-light/stdlib/string/regex-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,12 +991,13 @@ Optional<string> f$preg_replace(const mixed& pattern, const string& replacement,
}
}};

if (!regex_impl_::valid_preg_replace_mixed(pattern)) [[unlikely]] {
if (pattern.is_object()) [[unlikely]] {
kphp::log::warning("invalid pattern: object could not be converted to string");
return {};
}

if (pattern.is_string()) {
return f$preg_replace(pattern.as_string(), replacement, subject, limit, count);
if (!pattern.is_array()) {
return f$preg_replace(pattern.to_string(), replacement, subject, limit, count);
}

string result{subject};
Expand Down Expand Up @@ -1027,14 +1028,19 @@ Optional<string> f$preg_replace(const mixed& pattern, const mixed& replacement,
}
}};

if (!regex_impl_::valid_preg_replace_mixed(pattern) || !regex_impl_::valid_preg_replace_mixed(replacement)) [[unlikely]] {
if (pattern.is_object()) [[unlikely]] {
kphp::log::warning("invalid pattern: object could not be converted to string");
return {};
}
if (replacement.is_object()) [[unlikely]] {
kphp::log::warning("invalid replacement: object could not be converted to string");
return {};
}

if (replacement.is_string()) {
return f$preg_replace(pattern, replacement.as_string(), subject, limit, count);
if (!replacement.is_array()) {
return f$preg_replace(pattern, replacement.to_string(), subject, limit, count);
}
if (pattern.is_string()) [[unlikely]] {
if (!pattern.is_array()) [[unlikely]] {
kphp::log::warning("parameter mismatch: replacement is an array while pattern is string");
return {};
}
Expand Down Expand Up @@ -1075,13 +1081,21 @@ mixed f$preg_replace(const mixed& pattern, const mixed& replacement, const mixed
}
}};

if (!regex_impl_::valid_preg_replace_mixed(pattern) || !regex_impl_::valid_preg_replace_mixed(replacement) || !regex_impl_::valid_preg_replace_mixed(subject))
[[unlikely]] {
if (pattern.is_object()) [[unlikely]] {
kphp::log::warning("invalid pattern: object could not be converted to string");
return {};
}
if (replacement.is_object()) [[unlikely]] {
kphp::log::warning("invalid replacement: object could not be converted to string");
return {};
}
if (subject.is_object()) [[unlikely]] {
kphp::log::warning("invalid subject: object could not be converted to string");
return {};
}

if (subject.is_string()) {
return f$preg_replace(pattern, replacement, subject.as_string(), limit, count);
if (!subject.is_array()) {
return f$preg_replace(pattern, replacement, subject.to_string(), limit, count);
}

const auto& subject_arr{subject.as_array()};
Expand Down
30 changes: 12 additions & 18 deletions runtime-light/stdlib/string/regex-functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,6 @@ inline constexpr int64_t PREG_NOLIMIT = -1;

} // namespace kphp::regex

namespace regex_impl_ {

inline bool valid_preg_replace_mixed(const mixed& param) noexcept {
if (!param.is_array() && !param.is_string()) [[unlikely]] {
kphp::log::warning("invalid parameter: expected to be string or array");
return false;
}
return true;
}

} // namespace regex_impl_

using regexp = string;

// === preg_match =================================================================================
Expand Down Expand Up @@ -133,12 +121,13 @@ template<class F>
kphp::coro::task<Optional<string>> f$preg_replace_callback(mixed pattern, F callback, string subject, int64_t limit = kphp::regex::PREG_NOLIMIT,
Optional<std::variant<std::monostate, std::reference_wrapper<int64_t>>> opt_count = {},
int64_t flags = kphp::regex::PREG_NO_FLAGS) noexcept {
if (!regex_impl_::valid_preg_replace_mixed(pattern)) [[unlikely]] {
if (pattern.is_object()) [[unlikely]] {
kphp::log::warning("invalid pattern: object could not be converted to string");
co_return Optional<string>{};
}

if (pattern.is_string()) {
co_return co_await f$preg_replace_callback(std::move(pattern.as_string()), std::move(callback), std::move(subject), limit, opt_count, flags);
if (!pattern.is_array()) {
co_return co_await f$preg_replace_callback(pattern.to_string(), std::move(callback), std::move(subject), limit, opt_count, flags);
}

int64_t count{};
Expand Down Expand Up @@ -172,12 +161,17 @@ template<class F>
kphp::coro::task<mixed> f$preg_replace_callback(mixed pattern, F callback, mixed subject, int64_t limit = kphp::regex::PREG_NOLIMIT,
Optional<std::variant<std::monostate, std::reference_wrapper<int64_t>>> opt_count = {},
int64_t flags = kphp::regex::PREG_NO_FLAGS) noexcept {
if (!regex_impl_::valid_preg_replace_mixed(pattern) || !regex_impl_::valid_preg_replace_mixed(subject)) [[unlikely]] {
if (pattern.is_object()) [[unlikely]] {
kphp::log::warning("invalid pattern: object could not be converted to string");
co_return mixed{};
}
if (subject.is_object()) [[unlikely]] {
kphp::log::warning("invalid subject: object could not be converted to string");
co_return mixed{};
}

if (subject.is_string()) {
co_return co_await f$preg_replace_callback(std::move(pattern), std::move(callback), std::move(subject.as_string()), limit, opt_count, flags);
if (!subject.is_array()) {
co_return co_await f$preg_replace_callback(std::move(pattern), std::move(callback), subject.to_string(), limit, opt_count, flags);
}

int64_t count{};
Expand Down
1 change: 1 addition & 0 deletions tests/phpt/dl/004_preg_replace.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
var_dump(preg_replace(array('/[\w]+/'), array('$'), array('xyz', 'bdbd')));
var_dump(preg_replace(array('/\s+/', '~[b-d]~'), array('$'), array('x y', 'bd bc')));

var_dump(preg_replace('/a/', 42, 'a'));

/*
PHP 5.2.0 - 5.3.6 bug
Expand Down
Loading