Skip to content

Commit

Permalink
feat(language): drop segv handler
Browse files Browse the repository at this point in the history
  • Loading branch information
ObserverOfTime committed May 12, 2024
1 parent 5e70cbd commit 53e768c
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 49 deletions.
6 changes: 2 additions & 4 deletions tests/test_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ def setUp(self):
self.python = tree_sitter_python.language()
self.rust = tree_sitter_rust.language()

def test_init_not_positive(self):
def test_init_invalid(self):
self.assertRaises(ValueError, Language, -1)

def test_init_segv(self):
self.assertRaises(RuntimeError, Language, 1024)
self.assertRaises(ValueError, Language, 42)

def test_properties(self):
lang = Language(self.python)
Expand Down
45 changes: 4 additions & 41 deletions tree_sitter/binding/language.c
Original file line number Diff line number Diff line change
@@ -1,56 +1,19 @@
#include "language.h"

#ifndef _MSC_VER
#include <setjmp.h>
#include <signal.h>

static jmp_buf segv_jmp;

static void segfault_handler(int signal) {
if (signal == SIGSEGV) {
longjmp(segv_jmp, true);
}
}

// HACK: recover from invalid pointer using a signal handler (Unix)
TSLanguage *language_check_pointer(void *ptr) {
PyOS_setsig(SIGSEGV, segfault_handler);
if (!setjmp(segv_jmp)) {
__attribute__((unused)) volatile uint32_t version = ts_language_version((TSLanguage *)ptr);
} else {
PyErr_SetString(PyExc_RuntimeError, "Invalid TSLanguage pointer");
}
PyOS_setsig(SIGSEGV, SIG_DFL);
return PyErr_Occurred() ? NULL : (TSLanguage *)ptr;
}
#else
#include <windows.h>

// HACK: recover from invalid pointer using SEH (Windows)
TSLanguage *language_check_pointer(void *ptr) {
__try {
volatile uint32_t version = ts_language_version((TSLanguage *)ptr);
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH) {
PyErr_SetString(PyExc_RuntimeError, "Invalid TSLanguage pointer");
}
return PyErr_Occurred() ? NULL : (TSLanguage *)ptr;
}
#endif

int language_init(Language *self, PyObject *args, PyObject *Py_UNUSED(kwargs)) {
PyObject *language;
if (!PyArg_ParseTuple(args, "O:__init__", &language)) {
return -1;
}
if (PyLong_AsSsize_t(language) < 1) {
Py_ssize_t language_id = PyLong_AsSsize_t(language);
if (language_id < 1 || (language_id & 7) != 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "language ID must be positive");
PyErr_SetString(PyExc_ValueError, "invalid language ID");
}
return -1;
}

self->language = language_check_pointer(PyLong_AsVoidPtr(language));
self->language = PyLong_AsVoidPtr(language);
if (self->language == NULL) {
return -1;
}
Expand Down
15 changes: 12 additions & 3 deletions tree_sitter/binding/lookahead_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,24 @@ PyObject *lookahead_iterator_get_current_symbol_name(LookaheadIterator *self,

PyObject *lookahead_iterator_reset(LookaheadIterator *self, PyObject *args) {
TSLanguage *language;
PyObject *language_id;
PyObject *language_obj;
uint16_t state_id;
if (!PyArg_ParseTuple(args, "OH:reset", &language_id, &state_id)) {
if (!PyArg_ParseTuple(args, "OH:reset", &language_obj, &state_id)) {
return NULL;
}
if (REPLACE("reset()", "reset_state()") < 0) {
return NULL;
}
language = language_check_pointer(PyLong_AsVoidPtr(language_id));

Py_ssize_t language_id = PyLong_AsSsize_t(language_obj);
if (language_id < 1 || (language_id & 7) != 0) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "invalid language ID");
}
return NULL;
}

language = PyLong_AsVoidPtr(language_obj);
if (language == NULL) {
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion tree_sitter/binding/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ static PyGetSetDef tree_accessors[] = {
NULL},
{"text", (getter)tree_get_text, NULL,
PyDoc_STR("The source text of this tree, if unedited.\n\n"
".. deprecated:: 0.22.0\n Use ``root_node.text`` instead."),
".. deprecated:: 0.22.0\n\n Use ``root_node.text`` instead."),
NULL},
{"included_ranges", (getter)tree_get_included_ranges, NULL,
PyDoc_STR("The included ranges that were used to parse the syntax tree."), NULL},
Expand Down

0 comments on commit 53e768c

Please sign in to comment.