Skip to content

Commit

Permalink
fix: adjust checks in ForthMachine to prevent segfault when num_items…
Browse files Browse the repository at this point in the history
… is negative (#3209)

* Adjusted checks in case num_items is negative

* Added tests

* Added documentation for new rule

* Specify dtype for numpy arrays
  • Loading branch information
ariostas authored Aug 12, 2024
1 parent af232f5 commit 6eb8627
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
6 changes: 4 additions & 2 deletions awkward-cpp/src/libawkward/forth/ForthMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3075,7 +3075,7 @@ namespace awkward {
uint64_t tmp;
uint8_t tmpbyte;

if (items_remaining != 0) {
if (items_remaining > 0) {
tmpbyte = input->read_byte(current_error_);
if (current_error_ != util::ForthError::none) {
return;
Expand All @@ -3087,7 +3087,7 @@ namespace awkward {
}
data = tmp;
}
while (items_remaining != 0) {
while (items_remaining > 0) {
if (bits_wnd_r >= 8) {
bits_wnd_r -= 8;
bits_wnd_l -= 8;
Expand Down Expand Up @@ -3230,6 +3230,7 @@ namespace awkward {
break; \
}

if (num_items < 0) num_items = 0;
switch (format) {
case READ_BOOL: WRITE_DIRECTLY(bool, bool)
case READ_INT8: WRITE_DIRECTLY(int8_t, int8)
Expand Down Expand Up @@ -3311,6 +3312,7 @@ namespace awkward {
break; \
}

if (num_items < 0) num_items = 0;
switch (format) {
case READ_BOOL: WRITE_TO_STACK(bool)
case READ_INT8: WRITE_TO_STACK(int8_t)
Expand Down
14 changes: 14 additions & 0 deletions docs/reference/awkwardforth.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,20 @@ and
but the second is faster because it involves two Forth instructions and one ``memcpy``.

If the number of items to read is negative then it is interpreted as zero.

.. code-block:: python
>>> vm = ForthMachine32("""
... input x
... output y float32
...
... -1000000 x #d-> y
... """)
>>> vm.run({"x": np.arange(1000000) * 1.1})
>>> np.asarray(vm["y"])
array([], dtype=float32)
Type codes
""""""""""

Expand Down
45 changes: 45 additions & 0 deletions tests/test_3209_awkwardforth_read_negative_number_of_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# BSD 3-Clause License; see https://github.com/scikit-hep/awkward/blob/main/LICENSE

from __future__ import annotations

import numpy as np

import awkward as ak


def test_read_negative_number_of_items():
vm = ak.forth.ForthMachine32("input source -5 source #q-> stack")
vm.run({"source": np.array([1, 2, 3, 4, 5], dtype=np.int64)})
assert vm.stack == []

vm = ak.forth.ForthMachine32("input source output sink float64 -5 source #q-> sink")
vm.run({"source": np.array([1, 2, 3, 4, 5], dtype=np.int64)})
assert vm.output("sink").tolist() == []


def test_read_negative_and_positive_number_of_items():
vm = ak.forth.ForthMachine32(
"input source -5 source #q-> stack 5 source #q-> stack"
)
vm.run({"source": np.array([1, 2, 3, 4, 5], dtype=np.int64)})
assert vm.stack == [1, 2, 3, 4, 5]

vm = ak.forth.ForthMachine32(
"input source output sink float64 -5 source #q-> sink 5 source #q-> sink"
)
vm.run({"source": np.array([1, 2, 3, 4, 5], dtype=np.int64)})
assert vm.output("sink").tolist() == [1, 2, 3, 4, 5]


def test_read_positive_and_negative_number_of_items():
vm = ak.forth.ForthMachine32(
"input source 5 source #q-> stack -5 source #q-> stack"
)
vm.run({"source": np.array([1, 2, 3, 4, 5], dtype=np.int64)})
assert vm.stack == [1, 2, 3, 4, 5]

vm = ak.forth.ForthMachine32(
"input source output sink float64 5 source #q-> sink -5 source #q-> sink"
)
vm.run({"source": np.array([1, 2, 3, 4, 5], dtype=np.int64)})
assert vm.output("sink").tolist() == [1, 2, 3, 4, 5]

0 comments on commit 6eb8627

Please sign in to comment.