VYPR
High severityNVD Advisory· Published Jan 3, 2024· Updated Jun 17, 2025

Stack overflow in paddle.searchsorted

CVE-2023-52304

Description

Stack overflow in paddle.searchsorted in PaddlePaddle before 2.6.0. This flaw can lead to a denial of service, or even more damage.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Stack overflow in PaddlePaddle's paddle.searchsorted function before version 2.6.0 can lead to denial of service.

Root

Cause

CVE-2023-52304 describes a stack overflow vulnerability in the paddle.searchsorted function of PaddlePaddle, a deep learning framework. The issue exists in versions before 2.6.0 and arises from insufficient input validation. Specifically, the SearchsortedInferMeta function did not enforce that the input sorted_sequence tensor has at least one dimension, and the CastPyArg2Ints (and similar) functions failed to check whether a Python object is a Paddle tensor before treating it as a sequence [1][2]. This allowed a crafted input with zero or malformed dimensions to trigger unbounded recursion or excessive stack allocation.

Attack

Vector

An attacker can supply a specially crafted tensor to paddle.searchsorted that bypasses the missing dimension check. The vulnerability is exploitable without authentication if the attacker can invoke the API (e.g., through a model serving endpoint). The lack of a PADDLE_ENFORCE_GE guard on the sequence dimension size, combined with improper type-checking before sequence iteration, allows the function to enter an infinite or deeply nested loop, exhausting stack memory [2].

Impact

Successful exploitation leads to a stack overflow, causing a denial of service (DoS) by crashing the application. The advisory states that the flaw "can lead to a denial of service, or even more damage," implying potential for arbitrary code execution under certain conditions, though this is not elaborated in the available sources [1]. The vulnerability affects all deployments of PaddlePaddle using the affected function until patched.

Mitigation

The vulnerability is fixed in PaddlePaddle version 2.6.0. The fix adds a dimension check (PADDLE_ENFORCE_GE) in SearchsortedInferMeta and includes a type check (!PyObject_TypeCheck(obj, p_tensor_type)) in the sequence-casting helpers to avoid misidentifying tensors as generic sequences [2]. Users should upgrade to 2.6.0 or later. No workaround is documented. The PyPI advisory database lists this CVE with high severity, urging immediate update [4].

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.

PackageAffected versionsPatched versions
PaddlePaddlePyPI
< 2.6.02.6.0

Affected products

2

Patches

1
19da5c0c4d8c

fix security bug (#55782)

https://github.com/PaddlePaddle/PaddlewanghuancoderAug 2, 2023via ghsa
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

News mentions

0

No linked articles in our index yet.