From 5662a6b330e31134e54cf106f53638f2fe5d15a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Sun, 25 Feb 2018 17:01:31 +0100 Subject: [PATCH] Optimize Structure#validate and prevent AIOOBE in SAFEARRAY#read for zero dimensions --- CHANGES.md | 1 + .../src/com/sun/jna/platform/win32/OaIdl.java | 6 +++++- .../com/sun/jna/platform/win32/SAFEARRAYTest.java | 11 +++++++++++ src/com/sun/jna/Structure.java | 9 ++++++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 97b86158fc..8c8edcd778 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,7 @@ Bug Fixes * [#882](https://github.com/java-native-access/jna/pull/882): Correctly close file in `ELFAnalyser#runDetection`, fix suggested by [@Sylvyrfysh](https://github.com/Sylvyrfysh) in [#880](https://github.com/java-native-access/jna/pull/880) - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#887](https://github.com/java-native-access/jna/issues/887): MacFileUtils.moveToTrash() doesn't work in a sandboxed app fix suggested by [@sobakasu](https://github.com/sobakasu) - [@matthiasblaesing](https://github.com/matthiasblaesing). * [#894](https://github.com/java-native-access/jna/issues/894): NullPointerException can be caused by calling `com.sun.jna.platform.win32.COM.util.ProxyObject#dispose` multiple times - [@matthiasblaesing](https://github.com/matthiasblaesing). +* [#925](https://github.com/java-native-access/jna/issues/925): Optimize `Structure#validate` and prevent `ArrayIndexOutOfBoundsException` in `SAFEARRAY#read` for zero dimensions - [@matthiasblaesing](https://github.com/matthiasblaesing). Breaking Changes ---------------- diff --git a/contrib/platform/src/com/sun/jna/platform/win32/OaIdl.java b/contrib/platform/src/com/sun/jna/platform/win32/OaIdl.java index 84803740d1..908010cd99 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/OaIdl.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/OaIdl.java @@ -607,7 +607,11 @@ public SAFEARRAY(Pointer pointer) { @Override public void read() { super.read(); - rgsabound = (SAFEARRAYBOUND[]) rgsabound[0].toArray(cDims.intValue()); + if(cDims.intValue() > 0) { + rgsabound = (SAFEARRAYBOUND[]) rgsabound[0].toArray(cDims.intValue()); + } else { + rgsabound = new SAFEARRAYBOUND[]{ new SAFEARRAYBOUND() }; + } } @Override diff --git a/contrib/platform/test/com/sun/jna/platform/win32/SAFEARRAYTest.java b/contrib/platform/test/com/sun/jna/platform/win32/SAFEARRAYTest.java index 0caba84808..164f783e71 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/SAFEARRAYTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/SAFEARRAYTest.java @@ -13,6 +13,7 @@ package com.sun.jna.platform.win32; import com.sun.jna.Pointer; +import com.sun.jna.Structure; import com.sun.jna.platform.win32.COM.COMException; import com.sun.jna.platform.win32.COM.COMUtils; import com.sun.jna.platform.win32.COM.util.ObjectFactory; @@ -61,6 +62,7 @@ import static com.sun.jna.platform.win32.OaIdlUtil.toPrimitiveArray; import com.sun.jna.platform.win32.WTypes.VARTYPE; import com.sun.jna.platform.win32.WinDef.LONG; +import java.lang.reflect.Field; public class SAFEARRAYTest { static { @@ -82,6 +84,15 @@ public void testCreateVarArray() { SAFEARRAY varArray = SAFEARRAY.createSafeArray(1); Assert.assertTrue(varArray != null); } + + @Test + public void testCreateEmpty() throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { + Field f = Structure.class.getDeclaredField("PLACEHOLDER_MEMORY"); + f.setAccessible(true); + Pointer PLACEHOLDER_MEMORY = (Pointer) f.get(null); + SAFEARRAY sa = Structure.newInstance(SAFEARRAY.class, PLACEHOLDER_MEMORY); + Assert.assertTrue(sa != null); + } @Test public void testSafeArrayPutGetElement() throws Exception { diff --git a/src/com/sun/jna/Structure.java b/src/com/sun/jna/Structure.java index 13f3c14a83..42df030933 100644 --- a/src/com/sun/jna/Structure.java +++ b/src/com/sun/jna/Structure.java @@ -2125,6 +2125,13 @@ protected int getNativeSize(Class nativeType, Object value) { * @param cls Structure subclass to check */ static void validate(Class cls) { - Structure.newInstance(cls, PLACEHOLDER_MEMORY); + try { + cls.getConstructor(); + return; + }catch(NoSuchMethodException e) { + } + catch(SecurityException e) { + } + throw new IllegalArgumentException("No suitable constructor found for class: " + cls.getName()); } }