oceanbase / oceanbase/oceanbase

Oversized SDO_RELATE mask causes an unbounded stack allocation and ASan stack overflow

Open
#2,482 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
10.3k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

Self Checks
  • I have read the Contributing Guide.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.
OceanBase version

OceanBase CE 5.0.2.0, source revision d128661ca4f5b3d167c1928e556d70d2f901baef.

Self Hosted

Self Hosted (Source)

Environment

Ubuntu 22.04.5 LTS, x86_64, GCC 9.5.0, AddressSanitizer, 8 MiB process stack
limit. The attached poc.py needs Python 3, g++, and the affected OceanBase
source checkout.

Steps to reproduce
  1. Save the single attached file as poc.py.

  2. Run it on a disposable development host:

    python3 poc.py /path/to/oceanbase
    
  3. The script verifies the current VLA in
    ObQueryRange::get_spatial_relationship_by_mask(), compiles a minimal
    AddressSanitizer fixture for the same length-to-stack-allocation operation,
    runs ANYINTERACT as a control, and then supplies a 32 MiB mask.

Observed control:

control: ret=0 op=INTERSECTS

The compact attached PoC reports the same stack-overflow class with
parse_mask as its top frame:

AddressSanitizer:DEADLYSIGNAL
ERROR: AddressSanitizer: stack-overflow
    #0 parse_mask(...)
SUMMARY: AddressSanitizer: stack-overflow ... parse_mask
REPRODUCED: mask length controls an unbounded stack allocation

The current production function performs:

char cmp_str[upper_str.length() + 1];
cmp_str[upper_str.length()] = '\0';
MEMCPY(cmp_str, upper_str.ptr(), upper_str.length());

The authoritative source-anchored run compiled the exact current production
function. It had three clean controls and one ASan stack-overflow with return
code -6, with ObQueryRange::get_spatial_relationship_by_mask() as the top
frame. Its result SHA-256 is
76ed63b1a7484a73efc331fc986168339ada91edf743eb234deae5e6007189b2.

✔️ Expected Behavior

Spatial mask parsing should use bounded storage and reject an unreasonable
mask length before copying it. User-controlled length must not determine an
unbounded stack allocation.

❌ Actual Behavior

The function sizes a stack VLA directly from the mask length. A 32 MiB
component mask exhausts the thread stack and AddressSanitizer reports a stack
overflow in the current function.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at ObQueryRange::get_spatial_relationship_by_mask() and inspect the current VLA construction described in the issue. Run the attached poc.py against an OceanBase source checkout to reproduce the controls and ASan failure. Done means oversized masks are rejected before copying, bounded storage is used, and the 32 MiB case no longer causes a stack overflow.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.