From 19307694d9eec39135042bbf7ac35aee72ba4879 Mon Sep 17 00:00:00 2001 From: Vladislav Senin Date: Sun, 28 Jan 2024 17:04:53 +0300 Subject: [PATCH 1/3] fixed iconv function --- runtime/misc.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/runtime/misc.cpp b/runtime/misc.cpp index 62dfb24ead..5140837c55 100644 --- a/runtime/misc.cpp +++ b/runtime/misc.cpp @@ -70,18 +70,25 @@ Optional f$iconv(const string &input_encoding, const string &output_enco char *output_buf = output_str.buffer(); size_t res = iconv(cd, &input_buf, &input_len, &output_buf, &output_len); - if (res != (size_t)-1 || errno != E2BIG) { + // if errno is not E2BIG, then there is no need to allocate 4х more memory for a new string and try to call iconv function again + if (errno == E2BIG) { + /* + php_warning ("Error in iconv from \"%s\" to \"%s\" string \"%s\" at character %d at pos %d: %m", input_encoding.c_str(), output_encoding.c_str(), input_str.c_str(), (int)*input_buf, (int)(input_buf - input_str.c_str())); + */ + iconv(cd, nullptr, nullptr, nullptr, nullptr); + continue; + } + size_t len = output_buf - output_str.c_str(); + /* when passing the value false to the string constructor(size_type size, bool b), + * the new string will have an internal size identical to the one passed, + * however in some cases iconv will not write anything to the output_buf + * and thus the string will actually be empty + */ + if (res != (size_t)-1 && (len != 0 || *output_str.c_str() == '\0')) { output_str.shrink(static_cast(output_buf - output_str.c_str())); iconv_close(cd); return output_str; } -/* - if (errno != E2BIG) { - php_warning ("Error in iconv from \"%s\" to \"%s\" string \"%s\" at character %d at pos %d: %m", input_encoding.c_str(), output_encoding.c_str(), input_str.c_str(), (int)*input_buf, (int)(input_buf - input_str.c_str())); - break; - } -*/ - iconv(cd, nullptr, nullptr, nullptr, nullptr); } iconv_close(cd); From fec3cc34606a0f3887d914b4b0ebb01aa49e39b6 Mon Sep 17 00:00:00 2001 From: Vladislav Senin Date: Sun, 28 Jan 2024 17:05:50 +0300 Subject: [PATCH 2/3] added iconv tests and new tag 'binary', which open test result files with binary flag for comparing php and kphp --- tests/kphp_tester.py | 13 +++++++++---- tests/phpt/string_functions/010_iconv.php | 11 +++++++++++ tests/python/lib/kphp_run_once.py | 4 ++-- 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 tests/phpt/string_functions/010_iconv.php diff --git a/tests/kphp_tester.py b/tests/kphp_tester.py index 309913ff4e..ea01796b82 100755 --- a/tests/kphp_tester.py +++ b/tests/kphp_tester.py @@ -27,6 +27,9 @@ def __init__(self, file_path, test_tmp_dir, tags, env_vars: dict, out_regexps=No def is_ok(self): return "ok" in self.tags + def is_binary(self): + return "binary" in self.tags + def is_idempotent(self): return "non-idempotent" not in self.tags @@ -260,6 +263,7 @@ def run_warn_test(test: TestFile, runner): runner.kphp_build_stderr_artifact.error_priority = -1 return TestResult.passed(test, runner.artifacts) + def run_runtime_not_warn_test(test: TestFile, runner): if not runner.compile_with_kphp(test.env_vars): return TestResult.failed(test, runner.artifacts, "got kphp build error") @@ -275,6 +279,7 @@ def run_runtime_not_warn_test(test: TestFile, runner): return TestResult.passed(test, runner.artifacts) + def run_runtime_warn_test(test: TestFile, runner): if not runner.compile_with_kphp(test.env_vars): return TestResult.failed(test, runner.artifacts, "got kphp build error") @@ -300,7 +305,7 @@ def run_runtime_warn_test(test: TestFile, runner): return TestResult.passed(test, runner.artifacts) -def run_ok_test(test: TestFile, runner): +def run_ok_test(test: TestFile, runner, binary): # Run kphp test twice to check correctness in web-server alike environment with per request runtime reinitialization runs_cnt = 2 if test.is_idempotent() else 1 if not runner.run_with_php(runs_cnt=runs_cnt): @@ -309,7 +314,7 @@ def run_ok_test(test: TestFile, runner): return TestResult.failed(test, runner.artifacts, "got kphp build error") if not runner.run_with_kphp(runs_cnt=runs_cnt): return TestResult.failed(test, runner.artifacts, "got kphp runtime error") - if not runner.compare_php_and_kphp_stdout(): + if not runner.compare_php_and_kphp_stdout(binary=binary): return TestResult.failed(test, runner.artifacts, "got php and kphp diff") return TestResult.passed(test, runner.artifacts) @@ -322,7 +327,7 @@ def run_test(use_nocc, cxx_name, test: TestFile): runner = test.make_kphp_once_runner(use_nocc, cxx_name) runner.remove_artifacts_dir() - if test.is_php8() and runner._php_bin is None: # if php8 doesn't exist on a machine + if test.is_php8() and runner._php_bin is None: # if php8 doesn't exist on a machine test_result = TestResult.skipped(test) elif test.is_kphp_should_fail(): test_result = run_fail_test(test, runner) @@ -333,7 +338,7 @@ def run_test(use_nocc, cxx_name, test: TestFile): elif test.is_kphp_runtime_should_not_warn(): test_result = run_runtime_not_warn_test(test, runner) elif test.is_ok(): - test_result = run_ok_test(test, runner) + test_result = run_ok_test(test, runner, binary=test.is_binary()) else: test_result = TestResult.skipped(test) diff --git a/tests/phpt/string_functions/010_iconv.php b/tests/phpt/string_functions/010_iconv.php new file mode 100644 index 0000000000..a915c5f43d --- /dev/null +++ b/tests/phpt/string_functions/010_iconv.php @@ -0,0 +1,11 @@ +@ok binary + Date: Sun, 28 Jan 2024 17:27:28 +0300 Subject: [PATCH 3/3] added additional iconv tests --- tests/phpt/string_functions/010_iconv.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/phpt/string_functions/010_iconv.php b/tests/phpt/string_functions/010_iconv.php index a915c5f43d..2f36af1261 100644 --- a/tests/phpt/string_functions/010_iconv.php +++ b/tests/phpt/string_functions/010_iconv.php @@ -9,3 +9,12 @@ $empty = ""; var_dump(iconv('UTF-8', 'windows-1251', $empty)); + +// from examples: https://www.php.net/manual/en/function.iconv.php +$text = "This is the Euro symbol '€'."; +var_dump($text); +// TODO a strange bug when comparing via kphp_tester.py +//var_dump(iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text)); +// TODO works on MacOS but does not work on Linux +//var_dump(iconv("UTF-8", "ISO-8859-1//IGNORE", $text)); +var_dump(iconv("UTF-8", "ISO-8859-1", $text));