indygreg / indygreg/python-zstandard

`ZstdCompressionWriter()` constructs successfully but leads to `segmentation fault`

Đang mở
#331 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Ngôn ngữ chính
C
Star
642
Fork
116
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
5

Mô tả

I've been fuzzing Python C extension modules for a small research project.
I found a sanitizer issue which is a null-pointer dereference in ZstdCompressionWriter_memory_size.

I reproduced it with the binary wheel from a plain pip install zstandard.
The process terminates with SIGSEGV there as well.

I'm not sure whether zero-argument construction of this type is considered supported (calling ZstdCompressionWriter() with no arguments),
but since it currently terminates the interpreter rather than raising a Python exception, I thought it was worth reporting.

Versions

zstandard 0.25.0, cext backend, CPython 3.12, Linux x86_64.

Reproducer
import zstandard

w = zstandard.ZstdCompressionWriter()   # succeeds
w.memory_size()                         # SIGSEGV

Five calls across the two writer types behave the same way, each from a fresh direct construction:

class methods that segfault
ZstdCompressionWriter memory_size(), close(), flush()
ZstdDecompressionWriter memory_size(), flush()
Sanitizer build

Same call, zstandard built with -fsanitize=address,undefined:

c-ext/compressionwriter.c:64:65: runtime error:
    member access within null pointer of type 'ZstdCompressor'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
    c-ext/compressionwriter.c:64:65

AddressSanitizer: SEGV on unknown address 0x000000000020
    #0 ZstdCompressionWriter_memory_size  c-ext/compressionwriter.c:64:65

ZstdDecompressionWriter.memory_size() reports the equivalent at
c-ext/decompressionwriter.c:50:67.

Expected behavior

I think that direct construction should be rejected with a Python exception, as it is by the CFFI backend.

Under PYTHON_ZSTANDARD_IMPORT_POLICY=cffi the same construction is refused outright:

TypeError: ZstdCompressionWriter.__init__() missing 5 required positional
arguments: 'compressor', 'writer', 'source_size', 'write_size',
and 'write_return_read'
Actual behavior

The C extension permits construction with no arguments, leaving internal fields NULL.
Several methods dereference those fields and terminate the process with SIGSEGV.


Although these objects are normally obtained through stream_writer(), I wonder whether the C extension should reject zero-argument construction, as the CFFI backend already does, rather than produce an uninitialized object.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Trước tiên, hãy chạy Python reproducer, sau đó kiểm tra c-ext/compressionwriter.c:64 và c-ext/decompressionwriter.c:50 cùng với các đường dẫn khởi tạo writer. So sánh hành vi của C extension với CFFI backend đối với việc khởi tạo không có đối số. Hoàn thành khi việc khởi tạo trực tiếp không còn để lại các trường nội bộ NULL có thể truy cập và tạo ra một Python exception thay vì gây ra segfault.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
c, python
Lĩnh vực
backend
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Ít trao đổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
76/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.