From 3cee025c6708aa465109b3df4a9332ad9f4ef2e9 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Sat, 20 Apr 2024 11:02:38 +0200 Subject: [PATCH] Php::Value objects could crash if comparing non-string values with strings, fixes #524 --- include/value.h | 19 +++++++++++++------ zend/value.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/include/value.h b/include/value.h index 45f7464e..64653560 100644 --- a/include/value.h +++ b/include/value.h @@ -335,12 +335,12 @@ class PHPCPP_EXPORT Value : private HashParent * Comparison operators for hardcoded strings * @param value */ - bool operator==(const char *value) const { return ::strcmp(rawValue(), value) == 0; } - bool operator!=(const char *value) const { return ::strcmp(rawValue(), value) != 0; } - bool operator<=(const char *value) const { return ::strcmp(rawValue(), value) <= 0; } - bool operator>=(const char *value) const { return ::strcmp(rawValue(), value) >= 0; } - bool operator< (const char *value) const { return ::strcmp(rawValue(), value) < 0; } - bool operator> (const char *value) const { return ::strcmp(rawValue(), value) > 0; } + bool operator==(const char *value) const { return strcmp(value) == 0; } + bool operator!=(const char *value) const { return strcmp(value) != 0; } + bool operator<=(const char *value) const { return strcmp(value) <= 0; } + bool operator>=(const char *value) const { return strcmp(value) >= 0; } + bool operator< (const char *value) const { return strcmp(value) < 0; } + bool operator> (const char *value) const { return strcmp(value) > 0; } /** * Comparison operators for hardcoded Value @@ -424,6 +424,13 @@ class PHPCPP_EXPORT Value : private HashParent */ const char *rawValue() const; + /** + * Helper function for string comparison + * @param value + * @return int + */ + int strcmp(const char *value) const; + /** * Retrieve the value as number * diff --git a/zend/value.cpp b/zend/value.cpp index 6f53af42..e93826a1 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -1334,6 +1334,33 @@ const char *Value::rawValue() const return nullptr; } +/** + * Helper function for string comparison + * @param value + * @return int + */ +int Value::strcmp(const char *value) const +{ + // we need the string representation + zend_string *s = zval_get_string(_val); + + // remember size of the two strings + size_t valuelen = ::strlen(value); + size_t slen = ZSTR_LEN(s); + + // get the result for comparing the initial, overlapping, bytes + auto result = strncmp(ZSTR_VAL(s), value, std::min(valuelen, slen)); + + // we no longer need the string + zend_string_release(s); + + // if there are differences, we can expose thosw + if (result != 0) return result; + + // the shorter string comes first + return slen - valuelen; +} + /** * Retrieve the value as decimal * @return double