Segfault in paddle.mode
Description
OOB access in paddle.mode in PaddlePaddle before 2.6.0. This flaw can cause a runtime crash and a denial of service.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
An out-of-bounds read vulnerability in PaddlePaddle's paddle.mode can cause a denial of service via crafted input that bypasses type checks.
Vulnerability
Description
CVE-2023-38678 is an out-of-bounds (OOB) access vulnerability in the paddle.mode function of PaddlePaddle versions prior to 2.6.0. The root cause is insufficient input validation in the CastPyArg2Ints, CastPyArg2Longs, CastPyArg2Floats, and CastPyArg2Float64s helper functions. The functions check whether a Python object is a sequence using PySequence_Check, but fail to exclude PaddlePaddle tensor objects from that check. This allows a tensor value to be treated as a sequence, leading to an OOB read when the function attempts to iterate over the tensor's internal structure incorrectly [1][3].
Exploitation and
Attack Surface
An attacker can exploit this vulnerability by providing a specially crafted PaddlePaddle tensor as input to paddle.mode. No authentication is required if the attacker can supply data to a model that uses the vulnerable function. The fix [1] adds an additional type check (!PyObject_TypeCheck(obj, p_tensor_type)) to ensure tensor objects are not processed as generic sequences, preventing the incorrect memory access [1].
Impact
Successful exploitation causes a runtime crash and denial of service (DoS). The vulnerability does not appear to allow remote code execution or arbitrary memory write, as the OOB access is limited to a read operation that triggers a crash [3].
Mitigation
Users should upgrade to PaddlePaddle version 2.6.0 or later, which contains the fix for this vulnerability in the paddle.mode function via commit 19da5c0 [1][4]. No workarounds are available for unpatched versions. There is no evidence that CVE-2023-38678 has been added to the CISA Known Exploited Vulnerabilities (KEV) catalog.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
PaddlePaddlePyPI | < 2.6.0 | 2.6.0 |
Affected products
2- PaddlePaddle/PaddlePaddlev5Range: 0
Patches
119da5c0c4d8cfix security bug (#55782)
18 files changed · +90 −6
paddle/fluid/pybind/op_function_common.cc+4 −4 modified@@ -412,7 +412,7 @@ std::vector<int> CastPyArg2Ints(PyObject* obj, i)); } } - } else if (PySequence_Check(obj)) { + } else if (PySequence_Check(obj) && !PyObject_TypeCheck(obj, p_tensor_type)) { Py_ssize_t len = PySequence_Size(obj); value.reserve(len); PyObject* item = nullptr; @@ -488,7 +488,7 @@ std::vector<int64_t> CastPyArg2Longs(PyObject* obj, i)); } } - } else if (PySequence_Check(obj)) { + } else if (PySequence_Check(obj) && !PyObject_TypeCheck(obj, p_tensor_type)) { Py_ssize_t len = PySequence_Size(obj); PyObject* item = nullptr; for (Py_ssize_t i = 0; i < len; i++) { @@ -567,7 +567,7 @@ std::vector<float> CastPyArg2Floats(PyObject* obj, i)); } } - } else if (PySequence_Check(obj)) { + } else if (PySequence_Check(obj) && !PyObject_TypeCheck(obj, p_tensor_type)) { Py_ssize_t len = PySequence_Size(obj); PyObject* item = nullptr; for (Py_ssize_t i = 0; i < len; i++) { @@ -642,7 +642,7 @@ std::vector<double> CastPyArg2Float64s(PyObject* obj, i)); } } - } else if (PySequence_Check(obj)) { + } else if (PySequence_Check(obj) && !PyObject_TypeCheck(obj, p_tensor_type)) { Py_ssize_t len = PySequence_Size(obj); PyObject* item = nullptr; for (Py_ssize_t i = 0; i < len; i++) {
paddle/phi/infermeta/binary.cc+6 −0 modified@@ -2663,6 +2663,12 @@ void SearchsortedInferMeta(const MetaTensor& sorted_sequence, MetaTensor* out) { auto sequences_dims = sorted_sequence.dims(); auto values_dims = value.dims(); + PADDLE_ENFORCE_GE( + sequences_dims.size(), + 1, + phi::errors::InvalidArgument( + "Input sequences's dimension(%d) must be greater or equal than 1", + sequences_dims.size())); bool flag = true; if (sequences_dims.size() != values_dims.size()) {
paddle/phi/kernels/cpu/broadcast_kernel.cc+5 −0 modified@@ -28,6 +28,11 @@ void BroadcastKernel(const Context& dev_ctx, const DenseTensor& x, int root, DenseTensor* out) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("Tensor need be broadcast must not empyt.")); + #if defined(PADDLE_WITH_GLOO) dev_ctx.template Alloc<T>(out); auto comm_context =
paddle/phi/kernels/cpu/dot_kernel.cc+3 −0 modified@@ -27,6 +27,9 @@ void DotKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& y, DenseTensor* out) { + if (out->numel() <= 0) { + return; + } auto const *x_ptr = x.data<T>(), *x_ptr_ = &x_ptr[0]; auto const *y_ptr = y.data<T>(), *y_ptr_ = &y_ptr[0]; T* z = dev_ctx.template Alloc<T>(out);
paddle/phi/kernels/cpu/eig_kernel.cc+4 −0 modified@@ -24,6 +24,10 @@ void EigKernel(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out_w, DenseTensor* out_v) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + errors::InvalidArgument("EigKernel input tensor is empty.")); if (!IsComplexType(x.dtype())) { dev_ctx.template Alloc<phi::dtype::Complex<T>>(out_w); dev_ctx.template Alloc<phi::dtype::Complex<T>>(out_v);
paddle/phi/kernels/cpu/reduce_kernel.cc+4 −0 modified@@ -29,6 +29,10 @@ void ReduceKernel(const Context& dev_ctx, int root, int reduce_type, DenseTensor* out) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("Tensor need be reduced must not empyt.")); #if defined(PADDLE_WITH_GLOO) out->Resize(x.dims()); dev_ctx.template Alloc<T>(out);
paddle/phi/kernels/cpu/top_k_kernel.cc+6 −0 modified@@ -153,6 +153,12 @@ void TopkKernel(const Context& dev_ctx, } int k = k_scalar.to<int>(); + PADDLE_ENFORCE_GE( + x.numel(), + k, + errors::InvalidArgument( + "x has only %d element, can not find %d top values.", x.numel(), k)); + if (k_scalar.FromTensor()) { auto out_dims = out->dims(); // accroding to axis to set K value in the dim
paddle/phi/kernels/funcs/gather_scatter_functor.cc+0 −1 modified@@ -122,7 +122,6 @@ struct cpu_gather_scatter_functor { self_idx = is_scatter_like ? replace_index : index_idx; src_idx = is_scatter_like ? index_idx : replace_index; - reduce_op((tensor_t*)(self_data + self_idx), // NOLINT (tensor_t*)(src_data + src_idx)); // NOLINT index_idx++;
paddle/phi/kernels/funcs/reduce_function.h+9 −0 modified@@ -988,6 +988,10 @@ void ReduceKernel(const KPDevice& dev_ctx, const TransformOp& transform, const std::vector<int>& origin_reduce_dims, bool is_mean = false) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("Tensor need be reduced must not empyt.")); #ifdef PADDLE_WITH_XPU_KP auto stream = dev_ctx.x_context()->xpu_stream; #else @@ -1298,6 +1302,11 @@ void ReduceKernelImpl(const Context& dev_ctx, const std::vector<int64_t>& dims, bool keep_dim, bool reduce_all) { + PADDLE_ENFORCE_GT( + input.numel(), + 0, + phi::errors::InvalidArgument("Tensor need be reduced must not empyt.")); + dev_ctx.template Alloc<OutT>(output); if (reduce_all) {
paddle/phi/kernels/funcs/repeat_tensor2index_tensor.h+5 −0 modified@@ -32,6 +32,11 @@ void RepeatsTensor2IndexTensor(const Context& ctx, int64_t index_size = 0; for (int i = 0; i < repeats.dims()[0]; i++) { + PADDLE_ENFORCE_GE(repeats_data[i], + 0, + phi::errors::InvalidArgument( + "repeats must grater or equal than 0, but got %d", + repeats_data[i])); index_size += repeats_data[i]; } std::vector<RepeatsT> index_vec(index_size);
paddle/phi/kernels/gpu/broadcast_kernel.cu+5 −0 modified@@ -28,6 +28,11 @@ void BroadcastKernel(const Context& dev_ctx, const DenseTensor& x, int root, DenseTensor* out) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("Tensor need be broadcast must not empyt.")); + #if defined(PADDLE_WITH_NCCL) || defined(PADDLE_WITH_RCCL) dev_ctx.template Alloc<T>(out); gpuStream_t stream = dev_ctx.stream();
paddle/phi/kernels/gpu/dot_kernel.cu+3 −0 modified@@ -31,6 +31,9 @@ void DotKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& y, DenseTensor* out) { + if (out->numel() <= 0) { + return; + } dev_ctx.template Alloc<T>(out); if (out->dims().size() == 0) { auto eigen_out = phi::EigenScalar<T>::From(*out);
paddle/phi/kernels/gpu/lerp_kernel.cu+10 −0 modified@@ -51,6 +51,16 @@ void LerpKernel(const Context &ctx, const DenseTensor &y, const DenseTensor &weight, DenseTensor *out) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("LerpKernel's input x must not empyt.")); + + PADDLE_ENFORCE_GT( + y.numel(), + 0, + phi::errors::InvalidArgument("LerpKernel's input y must not empyt.")); + int rank = out->dims().size(); PADDLE_ENFORCE_GE( rank,
paddle/phi/kernels/gpu/reduce_kernel.cu+4 −0 modified@@ -29,6 +29,10 @@ void ReduceKernel(const Context& dev_ctx, int root, int reduce_type, DenseTensor* out) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("Tensor need be reduced must not empyt.")); #if defined(PADDLE_WITH_NCCL) || defined(PADDLE_WITH_RCCL) out->Resize(x.dims()); dev_ctx.template Alloc<T>(out);
paddle/phi/kernels/gpu/top_k_kernel.cu+5 −0 modified@@ -77,6 +77,11 @@ void TopkKernel(const Context& dev_ctx, if (axis < 0) axis += in_dims.size(); int k = k_scalar.to<int>(); + PADDLE_ENFORCE_GE( + x.numel(), + k, + errors::InvalidArgument( + "x has only %d element, can not find %d top values.", x.numel(), k)); if (k_scalar.FromTensor()) { phi::DDim out_dims = out->dims(); out_dims[axis] = k;
paddle/phi/kernels/impl/lerp_kernel_impl.h+10 −0 modified@@ -83,6 +83,16 @@ void LerpKernel(const Context& ctx, const DenseTensor& y, const DenseTensor& weight, DenseTensor* out) { + PADDLE_ENFORCE_GT( + x.numel(), + 0, + phi::errors::InvalidArgument("LerpKernel's input x must not empyt.")); + + PADDLE_ENFORCE_GT( + y.numel(), + 0, + phi::errors::InvalidArgument("LerpKernel's input y must not empyt.")); + int rank = out->dims().size(); PADDLE_ENFORCE_GE( rank,
paddle/phi/kernels/impl/repeat_interleave_kernel_impl.h+5 −0 modified@@ -58,6 +58,11 @@ void RepeatInterleaveKernel(const Context& ctx, int repeats, int dim, DenseTensor* out) { + PADDLE_ENFORCE_GT(repeats, + 0, + phi::errors::InvalidArgument( + "repeats must grater than 0, but got %d", repeats)); + auto place = ctx.GetPlace(); auto cpu_place = phi::CPUPlace();
python/paddle/tensor/manipulation.py+2 −1 modified@@ -543,6 +543,8 @@ def unstack(x, axis=0, num=None): raise ValueError( '`axis` must be in the range [-{0}, {0})'.format(x.ndim) ) + if num is not None and (num < 0 or num > x.shape[axis]): + raise ValueError(f'`num` must be in the range [0, {x.shape[axis]})') if in_dynamic_mode(): if num is None: num = x.shape[axis] @@ -4372,7 +4374,6 @@ def repeat_interleave(x, repeats, axis=None, name=None): if axis is None: x = paddle.flatten(x) axis = 0 - if in_dynamic_mode(): if isinstance(repeats, Variable): return _C_ops.repeat_interleave_with_tensor_index(x, repeats, axis)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-mr78-v55p-7777ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-38678ghsaADVISORY
- github.com/PaddlePaddle/Paddle/blob/develop/security/advisory/pdsa-2023-010.mdghsaWEB
- github.com/PaddlePaddle/Paddle/commit/19da5c0c4d8c5e4dfef2a92e24141c3f51884dccghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/paddlepaddle/PYSEC-2024-133.yamlghsaWEB
News mentions
0No linked articles in our index yet.