diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index 531abbc3..f3fbe29e 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -12,9 +12,19 @@ jobs: strategy: matrix: # macos-13 is for intel - os: ["ubuntu-24.04", "ubuntu-24.04-arm", "windows-latest", "windows-11-arm", "macos-13", "macos-latest"] + include: + - os: ubuntu-24.04 + - os: ubuntu-24.04-arm + - os: windows-latest + - os: windows-11-arm + - os: macos-13 + - os: macos-latest + - os: ubuntu-24.04 + cibw_archs: riscv64 + name_suffix: "-riscv64" + runs-on: ${{ matrix.os }} - name: Build wheels on ${{ matrix.os }} + name: Build wheels on ${{ matrix.os }}${{ matrix.name_suffix || '' }} steps: - uses: actions/checkout@v6 @@ -28,12 +38,19 @@ jobs: pip install -r requirements.txt make cython + - name: Set up QEMU for emulation + if: matrix.cibw_archs == 'riscv64' + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ matrix.cibw_archs }} + - name: Build uses: pypa/cibuildwheel@v3.3.0 env: CIBW_TEST_REQUIRES: "pytest" CIBW_TEST_COMMAND: "pytest {package}/test" CIBW_SKIP: "pp* cp38-* cp39-* cp310-win_arm64" + CIBW_ARCHS: ${{ matrix.cibw_archs || 'auto' }} - name: Build sdist if: runner.os == 'Linux' && runner.arch == 'X64' @@ -44,7 +61,7 @@ jobs: - name: Upload Wheels to artifact uses: actions/upload-artifact@v4 with: - name: wheels-${{ matrix.os }} + name: wheels-${{ matrix.os }}${{ matrix.name_suffix || '' }} path: wheelhouse # combine all wheels into one artifact diff --git a/msgpack/_unpacker.pyx b/msgpack/_unpacker.pyx index f0cf96d7..e25986ee 100644 --- a/msgpack/_unpacker.pyx +++ b/msgpack/_unpacker.pyx @@ -205,7 +205,10 @@ def unpackb(object packed, *, object object_hook=None, object list_hook=None, raise FormatError elif ret == -3: raise StackError - raise ValueError("Unpack failed: error = %d" % (ret,)) + elif PyErr_Occurred(): + raise + else: + raise ValueError("Unpack failed: error = %d" % (ret,)) cdef class Unpacker: @@ -481,6 +484,8 @@ cdef class Unpacker: raise FormatError elif ret == -3: raise StackError + elif PyErr_Occurred(): + raise else: raise ValueError("Unpack failed: error = %d" % (ret,)) diff --git a/msgpack/unpack.h b/msgpack/unpack.h index 58a2f4f5..0f9ffc05 100644 --- a/msgpack/unpack.h +++ b/msgpack/unpack.h @@ -70,12 +70,7 @@ static inline int unpack_callback_uint32(unpack_user* u, uint32_t d, msgpack_unp static inline int unpack_callback_uint64(unpack_user* u, uint64_t d, msgpack_unpack_object* o) { - PyObject *p; - if (d > LONG_MAX) { - p = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)d); - } else { - p = PyLong_FromLong((long)d); - } + PyObject *p = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)d); if (!p) return -1; *o = p; @@ -103,12 +98,9 @@ static inline int unpack_callback_int8(unpack_user* u, int8_t d, msgpack_unpack_ static inline int unpack_callback_int64(unpack_user* u, int64_t d, msgpack_unpack_object* o) { - PyObject *p; - if (d > LONG_MAX || d < LONG_MIN) { - p = PyLong_FromLongLong((PY_LONG_LONG)d); - } else { - p = PyLong_FromLong((long)d); - } + PyObject *p = PyLong_FromLongLong((PY_LONG_LONG)d); + if (!p) + return -1; *o = p; return 0; } diff --git a/msgpack/unpack_container_header.h b/msgpack/unpack_container_header.h index c14a3c2b..e48d43ba 100644 --- a/msgpack/unpack_container_header.h +++ b/msgpack/unpack_container_header.h @@ -45,7 +45,10 @@ static inline int unpack_container_header(unpack_context* ctx, const char* data, PyErr_SetString(PyExc_ValueError, "Unexpected type header on stream"); return -1; } - unpack_callback_uint32(&ctx->user, size, &ctx->stack[0].obj); + + if (unpack_callback_uint32(&ctx->user, size, &ctx->stack[0].obj) < 0) + return -1; + return 1; } diff --git a/test/test_except.py b/test/test_except.py index b77ac800..c56a6a30 100644 --- a/test/test_except.py +++ b/test/test_except.py @@ -4,7 +4,7 @@ from pytest import raises -from msgpack import FormatError, OutOfData, StackError, Unpacker, packb, unpackb +from msgpack import ExtType, FormatError, OutOfData, StackError, Unpacker, packb, unpackb class DummyException(Exception): @@ -32,6 +32,34 @@ def hook(obj): ) +def test_raise_from_list_hook(): + def hook(lst: list) -> list: + raise DummyException + + with raises(DummyException): + unpackb(packb([1, 2, 3]), list_hook=hook) + + with raises(DummyException): + unpacker = Unpacker(list_hook=hook) + unpacker.feed(packb([1, 2, 3])) + unpacker.unpack() + + +def test_raise_from_ext_hook(): + def hook(code: int, data: bytes) -> ExtType: + raise DummyException + + packed = packb(ExtType(42, b"hello")) + + with raises(DummyException): + unpackb(packed, ext_hook=hook) + + with raises(DummyException): + unpacker = Unpacker(ext_hook=hook) + unpacker.feed(packed) + unpacker.unpack() + + def test_invalidvalue(): incomplete = b"\xd9\x97#DL_" # raw8 - length=0x97 with raises(ValueError):