Skip to content

Commit 0c76c5a

Browse files
committed
big bandaid
1 parent 18631da commit 0c76c5a

File tree

5 files changed

+30
-25
lines changed

5 files changed

+30
-25
lines changed

src/mod.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,13 @@ static PyObject* handle(PyObject* self, PyObject* args) {
115115

116116
if (!params) params = PyTuple_New(0);
117117
if (!kwargs) kwargs = PyDict_New();
118-
int val = setjmp(buf);
118+
int val = getenv("POINTERSPY_ALLOW_SEGV") ? 0 : setjmp(buf);
119119

120120
if (val) {
121121
PyFrameObject* frame = PyEval_GetFrame();
122122
PyObject* name;
123123
PyCodeObject* code = NULL;
124-
124+
puts("1");
125125
if (frame) {
126126
code = GET_CODE(frame);
127127
name = Py_NewRef(code->co_name);
@@ -131,10 +131,10 @@ static PyObject* handle(PyObject* self, PyObject* args) {
131131
"__name__"
132132
);
133133
}
134+
puts("2");
134135

135136
Py_DECREF(frame);
136137

137-
// this is basically a copy of PyFrame_GetCode, which is only available on 3.9+
138138
PyErr_Format(
139139
PyExc_RuntimeError,
140140
"segment violation occured during execution of %S",

src/pointers/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
)
3232
from .std_structs import DivT, Lconv, LDivT, Tm
3333
from .structure import Struct, StructPointer
34-
from .util import NULL, Nullable, handle, raw_type, struct_cast
34+
from .util import NULL, Nullable, handle, raw_type, struct_cast, stop_handler
3535
from .var_pointer import VarPointer, to_var_ptr
3636

3737
__version__ = "3.0.0"

src/pointers/base_pointers.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import ctypes
2+
import gc
23
import sys
34
import weakref
45
from abc import ABC, abstractmethod
56
from contextlib import suppress
6-
from typing import (
7-
Any, Generic, Iterator, Optional, Tuple, Type, TypeVar, Union
8-
)
9-
10-
from typing_extensions import final
7+
from typing import (Any, Generic, Iterator, Optional, Tuple, Type, TypeVar,
8+
Union)
119

1210
from _pointers import add_ref, remove_ref
11+
from typing_extensions import final
1312

1413
from ._utils import deref, force_set_attr, move_to_mem
1514
from .exceptions import DereferenceError, FreedMemoryError, NullPointerError
@@ -390,6 +389,11 @@ def move(
390389
from .object_pointer import to_ptr
391390

392391
data_ptr = data if isinstance(data, BasePointer) else to_ptr(data)
392+
393+
if (sys.version_info.minor >= 11) and (gc.is_tracked(~data_ptr)):
394+
remove_ref(data)
395+
raise RuntimeError("allocation on tracked types is not supported on 3.11+")
396+
393397

394398
ptr, byte_stream = self._make_stream_and_ptr(
395399
sys.getsizeof(~data_ptr),
@@ -430,10 +434,9 @@ def _make_stream_and_ptr(
430434
size: int,
431435
address: int,
432436
) -> Tuple["ctypes._PointerLike", bytes]:
433-
434437
if self.freed:
435438
raise FreedMemoryError("memory has been freed")
436-
439+
437440
bytes_a = (ctypes.c_ubyte * size).from_address(address) # fmt: off
438441
return self.make_ct_pointer(), bytes(bytes_a)
439442

src/pointers/util.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import (
88
TYPE_CHECKING, Any, Callable, NamedTuple, Type, TypeVar, Union
99
)
10+
import os
1011
from _pointers import handle as _handle
1112
from typing_extensions import ParamSpec
1213
from .exceptions import SegmentViolation
@@ -25,6 +26,7 @@
2526
"raw_type",
2627
"handle",
2728
"struct_cast",
29+
"stop_handler"
2830
)
2931

3032
T = TypeVar("T")
@@ -50,6 +52,10 @@ def raw_type(ct: Type["ctypes._CData"]) -> Any:
5052
return RawType(ct)
5153

5254

55+
def stop_handler() -> None:
56+
"""Shutoff the SIGSEGV handler."""
57+
os.environ["POINTERSPY_ALLOW_SEGV"] = "1"
58+
5359
def handle(func: Callable[P, T]) -> Callable[P, T]:
5460
"""Handle segment violation errors when called."""
5561

@@ -85,4 +91,4 @@ def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
8591
@handle
8692
def struct_cast(ptr: Union["Struct", "StructPointer"]) -> Any:
8793
"""Cast a `Struct` or `StructPointer` to a Python object."""
88-
return ctypes.cast(ptr.get_existing_address(), ctypes.py_object).value
94+
return ctypes.cast(ptr.get_existing_address(), ctypes.py_object).value

tests/test_allocation.py

+9-13
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,9 @@
22

33
from ward import raises, test
44

5-
from pointers import (
6-
DereferenceError,
7-
FreedMemoryError,
8-
InvalidSizeError,
9-
StackAllocatedPointer,
10-
acquire_stack_alloc,
11-
calloc,
12-
free,
13-
malloc,
14-
realloc,
15-
)
5+
from pointers import (DereferenceError, FreedMemoryError, InvalidSizeError,
6+
StackAllocatedPointer, acquire_stack_alloc, calloc, free,
7+
malloc, realloc)
168

179

1810
@test("malloc and free")
@@ -57,6 +49,8 @@ def _():
5749

5850
@test("calloc")
5951
def _():
52+
if sys.version_info.minor >= 11:
53+
return
6054
ptr = calloc(4, 28)
6155
assert ptr.chunks == 4
6256

@@ -109,6 +103,8 @@ def _():
109103

110104
@test("allocation with tracked types")
111105
def _():
106+
if sys.version_info.minor >= 11:
107+
return
112108
class A:
113109
def __init__(self, value: str) -> None:
114110
self.value = value
@@ -124,7 +120,7 @@ def __init__(self, value: str) -> None:
124120

125121
@test("stack allocation")
126122
def _():
127-
@acquire_stack_alloc(24)
123+
@acquire_stack_alloc(28)
128124
def cb(ptr: StackAllocatedPointer[int]):
129125
assert type(ptr) is StackAllocatedPointer
130126

@@ -134,6 +130,6 @@ def cb(ptr: StackAllocatedPointer[int]):
134130
ptr <<= 0
135131

136132
with raises(InvalidSizeError):
137-
ptr <<= 1
133+
ptr <<= "hello"
138134

139135
assert ~ptr == 0

0 commit comments

Comments
 (0)