diff --git a/runtime-common/stdlib/serialization/serialization-context.h b/runtime-common/stdlib/serialization/serialization-context.h index 092ca0c54a..199b0bd907 100644 --- a/runtime-common/stdlib/serialization/serialization-context.h +++ b/runtime-common/stdlib/serialization/serialization-context.h @@ -8,10 +8,20 @@ #include #include #include +#include #include "common/mixin/not_copyable.h" +#include "common/php-functions.h" #include "common/wrappers/string_view.h" #include "runtime-common/core/runtime-core.h" +#include "runtime-common/core/utils/kphp-assert-core.h" +#include "runtime-light/core/reference-counter/reference-counter-functions.h" + +namespace kphp::serde::details { + +inline constexpr std::string_view JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE{"json_encode buffer overflow"}; + +} // namespace kphp::serde::details struct SerializationLibContext final : private vk::not_copyable { string last_json_processor_error; @@ -34,3 +44,15 @@ struct SerializationLibContext final : private vk::not_copyable { static SerializationLibContext& get() noexcept; }; + +struct SerializationLibConstants final : private vk::not_copyable { + string JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE{kphp::serde::details::JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE.data(), + kphp::serde::details::JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE.size()}; + + SerializationLibConstants() noexcept { + php_assert((kphp::core::set_reference_counter_recursive(JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE, ExtraRefCnt::for_global_const), + kphp::core::is_reference_counter_recursive(JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE, ExtraRefCnt::for_global_const))); + } + + static const SerializationLibConstants& get() noexcept; +}; diff --git a/runtime-light/state/image-state.h b/runtime-light/state/image-state.h index 389316405d..41e061dbe6 100644 --- a/runtime-light/state/image-state.h +++ b/runtime-light/state/image-state.h @@ -22,6 +22,7 @@ #include "runtime-light/stdlib/file/file-system-state.h" #include "runtime-light/stdlib/math/math-state.h" #include "runtime-light/stdlib/rpc/rpc-client-state.h" +#include "runtime-light/stdlib/serialization/serialization-state.h" #include "runtime-light/stdlib/string/string-state.h" #include "runtime-light/stdlib/time/time-state.h" #include "runtime-light/stdlib/visitors/shape-visitors.h" @@ -42,6 +43,7 @@ struct ImageState final : private vk::not_copyable { ShapeKeyDemangle shape_key_demangler; FileSystemImageState file_system_image_state; + SerializationImageState serialization_image_state; StringImageState string_image_state; TimeImageState time_image_state; MathImageState math_image_state; diff --git a/runtime-light/stdlib/serialization/json-functions.h b/runtime-light/stdlib/serialization/json-functions.h index e4a292e4f1..ad21cecef8 100644 --- a/runtime-light/stdlib/serialization/json-functions.h +++ b/runtime-light/stdlib/serialization/json-functions.h @@ -4,9 +4,12 @@ #pragma once +#include "common/containers/final_action.h" #include "runtime-common/core/runtime-core.h" #include "runtime-common/stdlib/serialization/json-functions.h" -#include "runtime-light/stdlib/diagnostics/logs.h" +#include "runtime-light/stdlib/diagnostics/exception-functions.h" +#include "runtime-light/stdlib/diagnostics/exception-types.h" +#include "runtime-light/stdlib/serialization/serialization-state.h" inline void f$set_json_log_on_timeout_mode([[maybe_unused]] bool enabled) noexcept {} @@ -15,13 +18,13 @@ string f$vk_json_encode_safe(const T& v, bool simple_encode = true) noexcept { auto& rt_ctx{RuntimeContext::get()}; rt_ctx.static_SB.clean(); rt_ctx.sb_lib_context.error_flag = STRING_BUFFER_ERROR_FLAG_ON; - impl_::JsonEncoder(0, simple_encode).encode(v, RuntimeContext::get().static_SB); + const auto finalizer{vk::finally([&rt_ctx] noexcept { rt_ctx.sb_lib_context.error_flag = STRING_BUFFER_ERROR_FLAG_OFF; })}; + + impl_::JsonEncoder(0, simple_encode).encode(v, rt_ctx.static_SB); if (rt_ctx.sb_lib_context.error_flag == STRING_BUFFER_ERROR_FLAG_FAILED) [[unlikely]] { rt_ctx.static_SB.clean(); - rt_ctx.sb_lib_context.error_flag = STRING_BUFFER_ERROR_FLAG_OFF; - kphp::log::error("vk_json_encode_safe tried to throw exception but it unsupported in runtime light"); + THROW_EXCEPTION(kphp::exception::make_throwable(SerializationImageState::get().JSON_ENCODE_BUFFER_OVERFLOW_EXCEPTION_MESSAGE)); return {}; } - rt_ctx.sb_lib_context.error_flag = STRING_BUFFER_ERROR_FLAG_OFF; return rt_ctx.static_SB.str(); } diff --git a/runtime-light/stdlib/serialization/serialization-state.cpp b/runtime-light/stdlib/serialization/serialization-state.cpp index 2e3f5eeaa8..29f6632898 100644 --- a/runtime-light/stdlib/serialization/serialization-state.cpp +++ b/runtime-light/stdlib/serialization/serialization-state.cpp @@ -4,8 +4,13 @@ #include "runtime-light/stdlib/serialization/serialization-state.h" +#include "runtime-light/state/image-state.h" #include "runtime-light/state/instance-state.h" SerializationInstanceState& SerializationInstanceState::get() noexcept { return InstanceState::get().serialization_instance_state; } + +const SerializationImageState& SerializationImageState::get() noexcept { + return ImageState::get().serialization_image_state; +} diff --git a/runtime-light/stdlib/serialization/serialization-state.h b/runtime-light/stdlib/serialization/serialization-state.h index 2f37e3ba6a..7a28b9fe39 100644 --- a/runtime-light/stdlib/serialization/serialization-state.h +++ b/runtime-light/stdlib/serialization/serialization-state.h @@ -7,3 +7,4 @@ #include "runtime-common/stdlib/serialization/serialization-context.h" using SerializationInstanceState = SerializationLibContext; +using SerializationImageState = SerializationLibConstants; diff --git a/runtime/serialize-context.cpp b/runtime/serialize-context.cpp index e0624e8f87..1022b5df73 100644 --- a/runtime/serialize-context.cpp +++ b/runtime/serialize-context.cpp @@ -9,3 +9,9 @@ static SerializationLibContext serialize_lib_context{}; SerializationLibContext& SerializationLibContext::get() noexcept { return serialize_lib_context; } + +const static SerializationLibConstants serialize_lib_constants{}; + +const SerializationLibConstants& SerializationLibConstants::get() noexcept { + return serialize_lib_constants; +} diff --git a/tests/phpt/dl/499_vk_json_encode_safe.php b/tests/phpt/dl/499_vk_json_encode_safe.php index 006ec66d3f..ecf890dc2b 100644 --- a/tests/phpt/dl/499_vk_json_encode_safe.php +++ b/tests/phpt/dl/499_vk_json_encode_safe.php @@ -1,4 +1,4 @@ -@ok k2_skip +@ok