From bca635da4b79c5f2559424cc798306d9bb6c22e2 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 30 Sep 2026 15:09:08 +0200 Subject: [PATCH] Read the count MEOS writes at the start of its int Fifteen methods of the object layer read the count a MEOS function writes into an int out-parameter, or the int it writes into a result buffer, at offset 0 of the four bytes they allocate: Temporal.time_split and time_split_n, TNumber.value_split and value_time_split, TPoint.values, stboxes and make_simple, STBox.quad_split_flat, IntSet.element_n, and value_set of TBool, TInt, TFloat, TText, TGeomPoint and TGeogPoint. Witness. Each read the int at offset 4 of a four-byte buffer. On the heap buffer Memory.allocate returns, getInt(4) throws ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4, so every one of these methods threw on any input; on the direct buffer of intset_value_n, IntSet.element_n read the four bytes past it. Measured. Against the catalog and libmeos of MobilityDB a362004728 with MEOS-API 20efba81be, nine of the fifteen answer, and the tests testValueSet, testValueSplit and testTimeSplit of TIntTest, testValuesStboxesMakeSimple of TGeomPointTest, testQuadSplitFlat of STBoxTest and testElementN of IntSetTest state their answers. The build succeeds and the suites run 106 and 1,805 tests, all passing. The other six stop further on: value_set of TBool, TFloat, TText, TGeomPoint and TGeogPoint appends to a null StringBuilder, and value_time_split hands MEOS a null argument. Why. MEOS writes an int out-parameter at its address, and the object layer reads it there. --- .../main/java/types/basic/tbool/TBool.java | 2 +- .../main/java/types/basic/tfloat/TFloat.java | 2 +- .../src/main/java/types/basic/tint/TInt.java | 2 +- .../java/types/basic/tnumber/TNumber.java | 4 +-- .../main/java/types/basic/tpoint/TPoint.java | 6 ++-- .../types/basic/tpoint/tgeog/TGeogPoint.java | 2 +- .../types/basic/tpoint/tgeom/TGeomPoint.java | 2 +- .../main/java/types/basic/ttext/TText.java | 2 +- .../src/main/java/types/boxes/STBox.java | 2 +- .../java/types/collections/number/IntSet.java | 2 +- .../main/java/types/temporal/Temporal.java | 4 +-- .../src/test/java/basic/TGeomPointTest.java | 19 ++++++++++++ jmeos-core/src/test/java/basic/TIntTest.java | 31 +++++++++++++++++++ jmeos-core/src/test/java/boxes/STBoxTest.java | 6 ++++ .../java/collections/number/IntSetTest.java | 5 +-- 15 files changed, 72 insertions(+), 19 deletions(-) diff --git a/jmeos-core/src/main/java/types/basic/tbool/TBool.java b/jmeos-core/src/main/java/types/basic/tbool/TBool.java index 62f1dc05c..303fdd055 100644 --- a/jmeos-core/src/main/java/types/basic/tbool/TBool.java +++ b/jmeos-core/src/main/java/types/basic/tbool/TBool.java @@ -138,7 +138,7 @@ default Set value_set(){ Pointer resPointer = GeneratedFunctions.tbool_values(this.getBoolInner(), intPointer); StringBuilder sb = null; sb.append("{"); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for (int i=0;i value_split(int size, int start){ Pointer listPointer = createEmptyPointerArray(runtime, size); Pointer result= GeneratedFunctions.tint_value_split(this.getNumberInner(), size, start, listPointer, intPointer); List tempList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for(int i=0;i value_time_split(Object duration, int value_size, int valu Pointer timeListPointer = createEmptyPointerArray(runtime, value_size); Pointer p= GeneratedFunctions.tint_value_time_split(this.getNumberInner(), value_size, dt, value_start, st, valueListPointer, timeListPointer, intPointer); List tempList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for(int i=0;i values(int precision){ Pointer intPointer = Memory.allocate(runtime, 4); Pointer resPointer= GeneratedFunctions.temporal_instants(this.getPointInner(), intPointer); List pointList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for(int i=0; i stboxes(){ Pointer intPointer = Memory.allocate(runtime, 4); Pointer resPointer= GeneratedFunctions.tgeo_stboxes(this.getPointInner(), intPointer); List stBoxList= new ArrayList<>(); - int length= intPointer.getInt(Integer.BYTES); + int length= intPointer.getInt(0); for(int i=0; i make_simple(){ // Allocate memory for an integer (4 bytes) but do not set a value Pointer intPointer = Memory.allocate(runtime, 4); Pointer resPointer= GeneratedFunctions.tpoint_make_simple(this.getPointInner(), intPointer); - int length= intPointer.getInt(Integer.BYTES); + int length= intPointer.getInt(0); List tPointList= new ArrayList<>(); TemporalType temporalType= getTemporalType(); String customType= getCustomType(); diff --git a/jmeos-core/src/main/java/types/basic/tpoint/tgeog/TGeogPoint.java b/jmeos-core/src/main/java/types/basic/tpoint/tgeog/TGeogPoint.java index b91dc4a0e..46f0a81e0 100644 --- a/jmeos-core/src/main/java/types/basic/tpoint/tgeog/TGeogPoint.java +++ b/jmeos-core/src/main/java/types/basic/tpoint/tgeog/TGeogPoint.java @@ -97,7 +97,7 @@ default GeographySet value_set(int precision) throws ParseException { Pointer intPointer = Memory.allocate(runtime, 4); Pointer resPointer= GeneratedFunctions.tgeo_values(this.getPointInner(), intPointer); List pointList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); StringBuilder sb = null; sb.append("{"); for(int i=0;i pointList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); StringBuilder sb = null; sb.append("{"); for(int i=0;i value_set(){ Pointer resPointer= GeneratedFunctions.ttext_values(this.getTextInner(), intPointer); StringBuilder sb= null; sb.append("{"); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for(int i=0; i quad_split_flat(){ // Allocate memory for an integer (4 bytes) but do not set a value Pointer intPointer = Memory.allocate(runtime, 4); Pointer resPointer= GeneratedFunctions.stbox_quad_split(this.get_inner(), intPointer); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); List stBoxList= new ArrayList<>(); for(int i=0;i elements(){ diff --git a/jmeos-core/src/main/java/types/temporal/Temporal.java b/jmeos-core/src/main/java/types/temporal/Temporal.java index 6091a335c..04a1a116d 100644 --- a/jmeos-core/src/main/java/types/temporal/Temporal.java +++ b/jmeos-core/src/main/java/types/temporal/Temporal.java @@ -1387,7 +1387,7 @@ public List time_split(Object duration, Object start){ Pointer listPointer = createEmptyPointerArray(runtime); Pointer p= GeneratedFunctions.temporal_time_split(this.inner, dt, st, listPointer, intPointer); List tempList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for(int i=0;i time_split_n(int n){ Pointer listPointer = createEmptyPointerArray(runtime); Pointer p= GeneratedFunctions.temporal_time_split(this.inner, dt, st, listPointer, intPointer); List tempList= new ArrayList<>(); - int count= intPointer.getInt(Integer.BYTES); + int count= intPointer.getInt(0); for(int i=0;i values = source.values(6); + assertEquals(2, values.size()); + assertEquals("POINT(1 1)@2019-09-01 00:00:00+00", values.get(0).to_string()); + assertEquals("POINT(2 2)@2019-09-02 00:00:00+00", values.get(1).to_string()); + assertEquals(1, source.stboxes().size()); + java.util.List simple = new TGeomPointSeq("[Point(0 0)@2019-09-01, Point(2 2)@2019-09-02, " + + "Point(2 0)@2019-09-03, Point(0 2)@2019-09-04]").make_simple(); + assertEquals(2, simple.size()); + assertEquals("[POINT(0 0)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00, " + + "POINT(2 0)@2019-09-03 00:00:00+00)", simple.get(0).to_string()); + assertEquals("[POINT(2 0)@2019-09-03 00:00:00+00, POINT(0 2)@2019-09-04 00:00:00+00]", + simple.get(1).to_string()); + } } diff --git a/jmeos-core/src/test/java/basic/TIntTest.java b/jmeos-core/src/test/java/basic/TIntTest.java index 0e980b19c..751c325ac 100644 --- a/jmeos-core/src/test/java/basic/TIntTest.java +++ b/jmeos-core/src/test/java/basic/TIntTest.java @@ -871,4 +871,35 @@ void testEverGreater(Temporal source, String type, int arg, boolean expected) { assertEquals(((TInt)source).never_greater_or_equal(arg),expected); assertEquals(((TInt)source).ever_greater_or_equal(arg),! expected); } + + + @org.junit.jupiter.api.Test + void testValueSet() { + GeneratedFunctions.meos_initialize_timezone("UTC"); + assertEquals("{1, 2}", new TIntSeq("[1@2019-09-01, 2@2019-09-02]").value_set().toString()); + } + + + @org.junit.jupiter.api.Test + void testValueSplit() { + GeneratedFunctions.meos_initialize_timezone("UTC"); + java.util.List fragments = new TIntSeq("[1@2019-09-01, 5@2019-09-02]").value_split(2, 0); + assertEquals(2, fragments.size()); + assertEquals("{[1@2019-09-01 00:00:00+00, 1@2019-09-02 00:00:00+00)}", ((TInt) fragments.get(0)).to_string()); + assertEquals("{[5@2019-09-02 00:00:00+00]}", ((TInt) fragments.get(1)).to_string()); + } + + + @org.junit.jupiter.api.Test + void testTimeSplit() { + GeneratedFunctions.meos_initialize_timezone("UTC"); + TIntSeq source = new TIntSeq("[1@2019-09-01, 5@2019-09-03]"); + for (java.util.List fragments : java.util.List.of( + source.time_split(java.time.Duration.ofDays(1), LocalDateTime.of(2019, 9, 1, 0, 0)), + source.time_split_n(2))) { + assertEquals(2, fragments.size()); + assertEquals("[1@2019-09-01 00:00:00+00, 1@2019-09-02 00:00:00+00)", ((TInt) fragments.get(0)).to_string()); + assertEquals("[1@2019-09-02 00:00:00+00, 5@2019-09-03 00:00:00+00]", ((TInt) fragments.get(1)).to_string()); + } + } } diff --git a/jmeos-core/src/test/java/boxes/STBoxTest.java b/jmeos-core/src/test/java/boxes/STBoxTest.java index 2b79913e4..89571ea3c 100644 --- a/jmeos-core/src/test/java/boxes/STBoxTest.java +++ b/jmeos-core/src/test/java/boxes/STBoxTest.java @@ -328,4 +328,10 @@ public void testAdjacent(String stbox, String stbox2, String expected) throws SQ } assertEquals(stb.is_adjacent(stb2),res); } + + + @org.junit.jupiter.api.Test + public void testQuadSplitFlat() { + assertEquals(4, new STBox("STBOX X((0,0),(4,4))").quad_split_flat().size()); + } } diff --git a/jmeos-core/src/test/java/collections/number/IntSetTest.java b/jmeos-core/src/test/java/collections/number/IntSetTest.java index 3311bc73f..17a98162b 100644 --- a/jmeos-core/src/test/java/collections/number/IntSetTest.java +++ b/jmeos-core/src/test/java/collections/number/IntSetTest.java @@ -83,14 +83,11 @@ public void testEndElements(){ assertEquals(3, intset.end_element()); } - /* @Test public void testElementN() throws Exception { - assertEquals(2, intset.element_n(2)); + assertEquals(2, intset.element_n(1)); } - */ - // @Test // public void testHash() throws Exception { // assertEquals(3969573766l, intset.hash());