Can't find the bug
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Jan 4 10:26:27 UTC 2023
Hi Bernd,
the problem in your code lies here:
```
((MemorySegment)strcat.invokeExact(buf, other))
.getUtf8String(0); //
<----------------------
```
That is, you are dereferencing the result of a "strcat" call. Now, while
you "know" that the resulting pointer will be a zero-terminated string
of some known size, the Java runtime has no way to know that. Attached
to the pointer there could be one char, two char, or infinite - the
linker has no way to know.
For this reason, all pointers returned by the linker are modelled as
"zero-length memory segments" (or ZLM in short). This is described here:
https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/MemorySegment.html#wrapping-addresses
To "resize" a ZLM you can create a _new_ segment, using the
MemorySegment::ofAddress factory, which takes a raw address, a size and
a scope.
Or, more simply, you can use an *unbounded* address layout when
constructing the downcall method handle, as this:
```
strcat = linker.downcallHandle(linker.defaultLookup().find("strcat").get(),
FunctionDescriptor.of(ADDRESS.asUnbounded(), ADDRESS, ADDRESS));
```
This will tell the linker to resize the returned segment to the maximal
size (Long.MAX_VALUE), which will make your dereference work.
Which path you take is up to you - the former gives you more control -
and more safety; the latter might be useful if you just want "things to
work". But both involve a "leap of faith" safety-wise, as the Java
runtime is trusting you to know what's coming out of that pointer. For
this reason, both paths will require a call to a so called "restricted"
method, which will produce a runtime warning (which can be useful when
diagnosing the source of unsafety in case of e.g. a JVM crash).
Hope this helps.
Maurizio
On 04/01/2023 07:52, Bernd Müller wrote:
> Dear Gavin,
>
> thank you very much for extracting the code.
> Eventually, it would be much easier to do a "mvn test". To do so
> please clone:
> https://urldefense.com/v3/__https://github.com/BerndMuller/ffm2__;!!ACWV5N9M2RV99hQ!PmaiPHl2BbBSjKjJr5SwpasFBcCCILMjVmcHQjs4n10ixKwpJyHK3aucRIBDoLKroPXW46Wtfvqm_mHjWecm3dfSiaicIK_yzGM$
>
> Error still:
> StdLibTest.foo:49->strcat:60 » IndexOutOfBounds Out of bound access on
> segment MemorySegment{ array: Optional.empty address:139631472807584
> limit: 0 }; new offset = 0; new length = 1
>
> looks for me like strcat changes the array size
>
> Kind Regards,
>
> Bernd
>
> Am 04.01.23 um 02:12 schrieb Gavin Ray:
>> Maurizio, the code I was able to get out of the email is below:
>>
>> public class StdLibTest {
>>
>> private static MethodHandle strlen; // C's strlen() function
>> private static MethodHandle strcat; // C's strcat() function
>>
>> @BeforeAll
>> public static void locateFunctions() {
>> Linker linker = Linker.nativeLinker();
>> strlen =
>> linker.downcallHandle(linker.defaultLookup().find("strlen").get(),
>> FunctionDescriptor.of(JAVA_LONG, ADDRESS));
>> strcat =
>> linker.downcallHandle(linker.defaultLookup().find("strcat").get(),
>> FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS));
>> }
>>
>>
>> @Test
>> public void strlen() throws Throwable {
>> try (Arena arena = Arena.openConfined()) {
>> MemorySegment segment = arena.allocateUtf8String("Hello");
>> int length = (int) (long) strlen.invoke(segment);
>> Assertions.assertSame(5, length);
>> }
>> }
>>
>> @Test
>> public void foo() throws Throwable {
>> String result = strcat("hello", "world");
>> }
>> /**
>> * This is a one to one copy of strcat test taken from
>> StdLibTest.java test from OpenJDK
>> */
>> String strcat(String s1, String s2) throws Throwable {
>> try (var arena = Arena.openConfined()) {
>> MemorySegment buf = arena.allocate(s1.length() + s2.length() + 1);
>> buf.setUtf8String(0, s1);
>> MemorySegment other = arena.allocateUtf8String(s2);
>> return ((MemorySegment)strcat.invokeExact(buf, other)).getUtf8String(0);
>> }
>> }
>> }
>>
>> On Tue, Jan 3, 2023 at 12:55 PM Maurizio Cimadamore
>> <maurizio.cimadamore at oracle.com
>> <mailto:maurizio.cimadamore at oracle.com>> wrote:
>>
>> Hi Bernd,
>> this mailing list truncates attachments. If you want us to look
>> at some
>> code you will have to paste it somewhere :-)
>>
>> Cheers
>> Maurizio
>>
>> On 03/01/2023 17:14, Bernd Müller wrote:
>> > Dear all,
>> >
>> > I try to train FFM. I even master quick sort but became
>> desperate on
>> > strcon.
>> >
>> > Attached you will find a Maven project with the strcon test
>> copied one
>> > to one from
>> > OpenJDK 20 sources.
>> >
>> > "mvn test" results in
>> >
>> > [ERROR] Errors:
>> > [ERROR] StdLibTest.foo:49->strcat:60 » IndexOutOfBounds Out
>> of bound
>> > access on segment MemorySegment{ array: Optional.empty
>> > address:139636573277136 limit: 0 }; new offset = 0; new length
>> = 1
>> >
>> > I am running OpenJDK 64-Bit Server VM (build 20-ea+29-2280, mixed
>> > mode, sharing) on Fedora 36.
>> >
>> > Please, can someone help ?
>> >
>> > Kind Regards,
>> >
>> > Bernd
>> >
>>
>
>
More information about the panama-dev
mailing list