Skip to content

move_median MEMORY_ERR without return — segfault under OOM #519

@devdanzin

Description

@devdanzin

When mm_new_nan (float path) or mm_new (int path) returns NULL under OOM, the MEMORY_ERR macro sets a MemoryError but does not return. Execution falls through to BN_BEGIN_ALLOW_THREADS (releasing the GIL with a pending exception), then dereferences the NULL mm pointer inside the computation loop — segfault.

File(s): move_template.c:568-570 (float), move_template.c:604-606 (int)

Reproducer:

import bottleneck as bn
import numpy as np
import _testcapi

arr = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
_testcapi.set_nomemory(1, 0)  # Fail all allocations
try:
    bn.move_median(arr, window=3)
    _testcapi.remove_mem_hooks()
except MemoryError:
    _testcapi.remove_mem_hooks()
# Segmentation fault (core dumped)

Crashes at n=1 because mm_new_nan uses raw malloc (hooked by _testcapi.set_nomemory).

Suggested fix: Add return NULL; after each MEMORY_ERR. Also free y from the INIT macro:

// Before:
if (mm == NULL) {
    MEMORY_ERR("Could not allocate memory for move_median");
}

// After:
if (mm == NULL) {
    MEMORY_ERR("Could not allocate memory for move_median");
    Py_DECREF(y);
    return NULL;
}

See #518 for the complete report.

Found using cext-review-toolkit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions