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); 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..2f36af1261 --- /dev/null +++ b/tests/phpt/string_functions/010_iconv.php @@ -0,0 +1,20 @@ +@ok binary +