Skip to content

Commit 0de51b3

Browse files
Merge pull request #1326 from matthiasblaesing/share_internal_memory
Ensure pointers indirected from Memory and pointing into Memory should retain originating object
2 parents 25194e1 + 5d23330 commit 0de51b3

File tree

6 files changed

+344
-7
lines changed

6 files changed

+344
-7
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ pom-jna-platform.xml.asc
3030
/contrib/platform/${build.generated.sources.dir}/
3131
/contrib/platform/${build}/
3232
/contrib/platform/nbproject/private/
33-
/nbproject/private/
33+
/nbproject/private/
34+
/native/.ccls-cache/

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Bug Fixes
1414
---------
1515
* [#1317](https://github.com/java-native-access/jna/pull/1317): Change the maven coordinates of the JPMS artifacts from classifier `jpms` to custom artifact ids `jna-jpms` and `jna-platform-jpms` - [@matthiasblaesing](https://github.com/matthiasblaesing).
1616
* [#1322](https://github.com/java-native-access/jna/pull/1322): Handle 0-length domain names in `c.s.j.p.win32.Advapi32Util#getAccountBySid` - [@dbwiddis](https://github.com/dbwiddis).
17+
* [#1326](https://github.com/java-native-access/jna/pull/1326): Ensure pointers indirected from Memory and pointing into Memory retain originating object - [@matthiasblaesing](https://github.com/matthiasblaesing).
1718

1819
Important Changes
1920
-----------------

nbproject/ide-file-targets.xml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project basedir=".." name="JNA-IDE">
3+
<target name="run-selected-file-in-src">
4+
<fail unless="run.class">Must set property 'run.class'</fail>
5+
6+
<subant antfile="build.xml" buildpath="${basedir}" target="compile-tests"/>
7+
8+
<java classname="${run.class}" failonerror="true" fork="true">
9+
<classpath>
10+
<pathelement path="build/classes"/>
11+
<pathelement path="build/test-classes"/>
12+
</classpath>
13+
</java>
14+
</target>
15+
<target name="debug-selected-file-in-src">
16+
<fail unless="debug.class">Must set property 'debug.class'</fail>
17+
18+
<subant antfile="build.xml" buildpath="${basedir}" target="compile-tests"/>
19+
20+
<path id="cp">
21+
<pathelement path="build/classes"/>
22+
<pathelement path="build/test-classes"/>
23+
</path>
24+
<nbjpdastart addressproperty="jpda.address" name="JNA" transport="dt_socket">
25+
<classpath refid="cp"/>
26+
</nbjpdastart>
27+
<java classname="${debug.class}" fork="true">
28+
<classpath refid="cp"/>
29+
<jvmarg value="-agentlib:jdwp=transport=dt_socket,address=${jpda.address}"/>
30+
</java>
31+
</target>
32+
33+
<target name="run-selected-file-in-test">
34+
<fail unless="run.class">Must set property 'run.class'</fail>
35+
36+
<subant antfile="build.xml" buildpath="${basedir}" target="compile-tests"/>
37+
38+
<java classname="${run.class}" failonerror="true" fork="true">
39+
<classpath>
40+
<pathelement path="lib/hamcrest-core-1.3.jar:lib/junit.jar:lib/test/dom4j-1.6.1.jar:lib/test/guava-27.1-jre.jar:lib/test/javassist-3.12.1.GA.jar:lib/test/reflections-0.9.11.jar:lib/test/slf4j-api-1.6.1.jar"/>
41+
<pathelement path="build/jna.jar"/>
42+
<pathelement path="build/test-classes"/>
43+
</classpath>
44+
</java>
45+
</target>
46+
47+
<target name="debug-selected-file-in-test">
48+
<fail unless="debug.class">Must set property 'debug.class'</fail>
49+
50+
<subant antfile="build.xml" buildpath="${basedir}" target="compile-tests"/>
51+
52+
<path id="cp">
53+
<pathelement path="lib/hamcrest-core-1.3.jar:lib/junit.jar:lib/test/dom4j-1.6.1.jar:lib/test/guava-27.1-jre.jar:lib/test/javassist-3.12.1.GA.jar:lib/test/reflections-0.9.11.jar:lib/test/slf4j-api-1.6.1.jar"/>
54+
<pathelement path="build/jna.jar"/>
55+
<pathelement path="build/test-classes"/>
56+
</path>
57+
<nbjpdastart addressproperty="jpda.address" name="JNA" transport="dt_socket">
58+
<classpath refid="cp"/>
59+
</nbjpdastart>
60+
<java classname="${debug.class}" fork="true">
61+
<classpath refid="cp"/>
62+
<jvmarg value="-agentlib:jdwp=transport=dt_socket,address=${jpda.address}"/>
63+
</java>
64+
</target>
65+
</project>

nbproject/project.xml

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,58 @@ auxiliary.show.customizer.message=<message>
5656
<target>clean</target>
5757
<target>jar</target>
5858
</action>
59+
<action name="run.single">
60+
<script>nbproject/ide-file-targets.xml</script>
61+
<target>run-selected-file-in-src</target>
62+
<context>
63+
<property>run.class</property>
64+
<folder>src</folder>
65+
<pattern>\.java$</pattern>
66+
<format>java-name</format>
67+
<arity>
68+
<one-file-only/>
69+
</arity>
70+
</context>
71+
</action>
72+
<action name="debug.single">
73+
<script>nbproject/ide-file-targets.xml</script>
74+
<target>debug-selected-file-in-src</target>
75+
<context>
76+
<property>debug.class</property>
77+
<folder>src</folder>
78+
<pattern>\.java$</pattern>
79+
<format>java-name</format>
80+
<arity>
81+
<one-file-only/>
82+
</arity>
83+
</context>
84+
</action>
85+
<action name="debug.single">
86+
<script>nbproject/ide-file-targets.xml</script>
87+
<target>debug-selected-file-in-test</target>
88+
<context>
89+
<property>debug.class</property>
90+
<folder>test</folder>
91+
<pattern>\.java$</pattern>
92+
<format>java-name</format>
93+
<arity>
94+
<one-file-only/>
95+
</arity>
96+
</context>
97+
</action>
98+
<action name="run.single">
99+
<script>nbproject/ide-file-targets.xml</script>
100+
<target>run-selected-file-in-test</target>
101+
<context>
102+
<property>run.class</property>
103+
<folder>test</folder>
104+
<pattern>\.java$</pattern>
105+
<format>java-name</format>
106+
<arity>
107+
<one-file-only/>
108+
</arity>
109+
</context>
110+
</action>
59111
</ide-actions>
60112
<view>
61113
<items>
@@ -94,7 +146,7 @@ auxiliary.show.customizer.message=<message>
94146
<compilation-unit>
95147
<package-root>test</package-root>
96148
<unit-tests/>
97-
<classpath mode="compile">lib/hamcrest-core-1.3.jar:lib/junit.jar:lib/test/dom4j-1.6.1.jar:lib/test/guava-11.0.2.jar:lib/test/javassist-3.12.1.GA.jar:lib/test/reflections-0.9.11.jar:lib/test/slf4j-api-1.6.1.jar:src</classpath>
149+
<classpath mode="compile">lib/hamcrest-core-1.3.jar:lib/junit.jar:lib/test/dom4j-1.6.1.jar:lib/test/guava-27.1-jre.jar:lib/test/javassist-3.12.1.GA.jar:lib/test/reflections-0.9.11.jar:lib/test/slf4j-api-1.6.1.jar:src</classpath>
98150
<source-level>1.8</source-level>
99151
</compilation-unit>
100152
<compilation-unit>

src/com/sun/jna/Memory.java

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ public void read(long bOff, short[] buf, int index, int length) {
400400
*/
401401
@Override
402402
public void read(long bOff, char[] buf, int index, int length) {
403-
boundsCheck(bOff, length * 2L);
403+
boundsCheck(bOff, length * Native.WCHAR_SIZE);
404404
super.read(bOff, buf, index, length);
405405
}
406406

@@ -460,6 +460,20 @@ public void read(long bOff, double[] buf, int index, int length) {
460460
super.read(bOff, buf, index, length);
461461
}
462462

463+
/**
464+
* Indirect the native pointer to <code>malloc</code> space, a la
465+
* <code>Pointer.read</code>. But this method performs a bounds checks to
466+
* ensure that the indirection does not cause memory outside the
467+
* <code>malloc</code>ed space to be accessed.
468+
*
469+
* @see Pointer#read(long,Pointer[],int,int)
470+
*/
471+
@Override
472+
public void read(long bOff, Pointer[] buf, int index, int length) {
473+
boundsCheck(bOff, length * Native.POINTER_SIZE);
474+
super.read(bOff, buf, index, length);
475+
}
476+
463477
//////////////////////////////////////////////////////////////////////////
464478
// Raw write methods
465479
//////////////////////////////////////////////////////////////////////////
@@ -502,7 +516,7 @@ public void write(long bOff, short[] buf, int index, int length) {
502516
*/
503517
@Override
504518
public void write(long bOff, char[] buf, int index, int length) {
505-
boundsCheck(bOff, length * 2L);
519+
boundsCheck(bOff, length * Native.WCHAR_SIZE);
506520
super.write(bOff, buf, index, length);
507521
}
508522

@@ -562,6 +576,20 @@ public void write(long bOff, double[] buf, int index, int length) {
562576
super.write(bOff, buf, index, length);
563577
}
564578

579+
/**
580+
* Indirect the native pointer to <code>malloc</code> space, a la
581+
* <code>Pointer.write</code>. But this method performs a bounds
582+
* checks to ensure that the indirection does not cause memory outside the
583+
* <code>malloc</code>ed space to be accessed.
584+
*
585+
* @see Pointer#write(long,Pointer[],int,int)
586+
*/
587+
@Override
588+
public void write(long bOff, Pointer[] buf, int index, int length) {
589+
boundsCheck(bOff, length * Native.POINTER_SIZE);
590+
super.write(bOff, buf, index, length);
591+
}
592+
565593
//////////////////////////////////////////////////////////////////////////
566594
// Java type read methods
567595
//////////////////////////////////////////////////////////////////////////
@@ -590,7 +618,7 @@ public byte getByte(long offset) {
590618
*/
591619
@Override
592620
public char getChar(long offset) {
593-
boundsCheck(offset, 1);
621+
boundsCheck(offset, Native.WCHAR_SIZE);
594622
return super.getChar(offset);
595623
}
596624

@@ -675,7 +703,7 @@ public double getDouble(long offset) {
675703
@Override
676704
public Pointer getPointer(long offset) {
677705
boundsCheck(offset, Native.POINTER_SIZE);
678-
return super.getPointer(offset);
706+
return shareReferenceIfInBounds(super.getPointer(offset));
679707
}
680708

681709
/**
@@ -862,4 +890,26 @@ protected static long malloc(long size) {
862890
public String dump() {
863891
return dump(0, (int)size());
864892
}
893+
894+
/**
895+
* Check whether the supplied Pointer object points into the memory region
896+
* backed by this memory object. The intention is to prevent premature GC
897+
* of the Memory object.
898+
*
899+
* @param target Pointer to check
900+
* @return {@code target} if target does not point into the region covered
901+
* by this memory object, a newly {@code SharedMemory} object, if the pointer
902+
* points to memory backed by this Memory object.
903+
*/
904+
private Pointer shareReferenceIfInBounds(Pointer target) {
905+
if(target == null) {
906+
return null;
907+
}
908+
long offset = target.peer - this.peer;
909+
if (offset >= 0 && offset < this.size) {
910+
return this.share(offset);
911+
} else {
912+
return target;
913+
}
914+
}
865915
}

0 commit comments

Comments
 (0)