Skip to content

Commit 3555c4e

Browse files
author
Lauri Wiljami Ahonen
committed
Fix bug in VARDESC, TYPEDESC, and FUNCDESC causing illegal memory access. The types contained an array that might be zero-sized, but JNA tried to read at least one item.
1 parent 89ea87e commit 3555c4e

File tree

4 files changed

+274
-15
lines changed

4 files changed

+274
-15
lines changed

contrib/platform/src/com/sun/jna/platform/win32/OaIdl.java

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,16 @@ public static class SAFEARRAY extends Structure implements Closeable {
553553

554554
public static class ByReference extends SAFEARRAY implements
555555
Structure.ByReference {
556+
557+
public ByReference() {
558+
super();
559+
}
560+
561+
public ByReference(Pointer pointer) {
562+
super(pointer);
563+
this.read();
564+
}
565+
556566
}
557567

558568
public USHORT cDims;
@@ -1316,12 +1326,46 @@ public FUNCDESC() {
13161326
public FUNCDESC(Pointer pointer) {
13171327
super(pointer);
13181328
this.read();
1329+
}
1330+
1331+
@Override
1332+
public void read() {
1333+
// Read cParams first to know the correct array size for lprgelemdescParam
1334+
readField("cParams");
1335+
int paramCount = this.cParams.shortValue();
1336+
1337+
// Read most fields except lprgelemdescParam
1338+
for (String field : new String[]{
1339+
"memid", "lprgscode", "funckind", "invkind",
1340+
"callconv", "cParamsOpt", "oVft", "cScodes", "elemdescFunc", "wFuncFlags"}) {
1341+
readField(field);
1342+
}
13191343

1320-
if (this.cParams.shortValue() > 1) {
1321-
this.lprgelemdescParam.elemDescArg = new ELEMDESC[this.cParams
1322-
.shortValue()];
1323-
this.lprgelemdescParam.read();
1344+
// Handle lprgelemdescParam specially based on paramCount
1345+
if (paramCount > 0) {
1346+
readField("lprgelemdescParam");
1347+
if (this.lprgelemdescParam != null) {
1348+
this.lprgelemdescParam.elemDescArg = new ELEMDESC[paramCount];
1349+
this.lprgelemdescParam.read();
1350+
}
13241351
}
1352+
// When paramCount=0, don't read lprgelemdescParam to avoid reading garbage
1353+
}
1354+
1355+
@Override
1356+
public void write() {
1357+
// Write most fields except lprgelemdescParam
1358+
for (String field : new String[]{
1359+
"memid", "lprgscode", "funckind", "invkind",
1360+
"callconv", "cParams", "cParamsOpt", "oVft", "cScodes", "elemdescFunc", "wFuncFlags"}) {
1361+
writeField(field);
1362+
}
1363+
1364+
// Handle lprgelemdescParam specially based on cParams
1365+
if (this.cParams != null && this.cParams.shortValue() > 0) {
1366+
writeField("lprgelemdescParam");
1367+
}
1368+
// When cParams=0, don't write lprgelemdescParam
13251369
}
13261370
}
13271371

@@ -1398,14 +1442,10 @@ public static class ByReference extends _VARDESC implements
13981442
public VARIANT.ByReference lpvarValue;
13991443

14001444
public _VARDESC() {
1401-
setType("lpvarValue");
1402-
this.read();
14031445
}
14041446

14051447
public _VARDESC(Pointer pointer) {
14061448
super(pointer);
1407-
setType("lpvarValue");
1408-
this.read();
14091449
}
14101450

14111451
/**
@@ -1431,9 +1471,17 @@ public VARDESC() {
14311471

14321472
public VARDESC(Pointer pointer) {
14331473
super(pointer);
1434-
this._vardesc.setType("lpvarValue");
14351474
this.read();
14361475
}
1476+
1477+
@Override
1478+
public void read() {
1479+
readField("varkind");
1480+
if (_vardesc != null) {
1481+
_vardesc.setType(varkind.value == VARKIND.VAR_CONST ? "lpvarValue" : "oInst");
1482+
}
1483+
super.read();
1484+
}
14371485
}
14381486

14391487
@FieldOrder({"tdesc", "_elemdesc"})
@@ -1654,14 +1702,10 @@ public static class _TYPEDESC extends Union {
16541702
public HREFTYPE hreftype;
16551703

16561704
public _TYPEDESC() {
1657-
this.setType("hreftype");
1658-
this.read();
16591705
}
16601706

16611707
public _TYPEDESC(Pointer pointer) {
16621708
super(pointer);
1663-
this.setType("hreftype");
1664-
this.read();
16651709
}
16661710

16671711
public TYPEDESC.ByReference getLptdesc() {
@@ -1687,18 +1731,44 @@ public HREFTYPE getHreftype() {
16871731
public VARTYPE vt;
16881732

16891733
public TYPEDESC() {
1690-
this.read();
16911734
}
16921735

16931736
public TYPEDESC(Pointer pointer) {
16941737
super(pointer);
1695-
this.read();
16961738
}
16971739

16981740
public TYPEDESC(_TYPEDESC _typedesc, VARTYPE vt) {
16991741
this._typedesc = _typedesc;
17001742
this.vt = vt;
17011743
}
1744+
1745+
@Override
1746+
public void read() {
1747+
Pointer p = getPointer();
1748+
if (p == null) {
1749+
return;
1750+
}
1751+
1752+
// Read vt first to determine the correct union type
1753+
readField("vt");
1754+
1755+
// Set the union type based on vt discriminator
1756+
switch (vt.intValue()) {
1757+
case Variant.VT_PTR:
1758+
case Variant.VT_SAFEARRAY:
1759+
_typedesc.setType("lptdesc");
1760+
break;
1761+
case Variant.VT_CARRAY:
1762+
_typedesc.setType("lpadesc");
1763+
break;
1764+
case Variant.VT_USERDEFINED:
1765+
default:
1766+
_typedesc.setType("hreftype");
1767+
break;
1768+
}
1769+
1770+
super.read();
1771+
}
17021772
}
17031773

17041774
@FieldOrder({"dwReserved", "wIDLFlags"})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* Copyright (c) 2024 Lauri Ahonen, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32.COM;
25+
26+
import com.sun.jna.platform.win32.OaIdl;
27+
28+
/**
29+
* Test for TYPEDESC and FUNCDESC union handling.
30+
* This test iterates through functions in a Shell32 type library interface
31+
* and verifies that JNA correctly reads the discriminated unions in TYPEDESC
32+
* and handles the lprgelemdescParam array correctly when cParams=0.
33+
*/
34+
public class InvalidMemoryAccessBug {
35+
public static void main(String[] args) {
36+
TypeLibUtil libUtil = new TypeLibUtil("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}", 1, 0); // C:\Windows\SysWOW64\shell32.dll
37+
int typeIndex = 21;
38+
39+
ITypeInfo typeInfo = libUtil.getTypeInfo(typeIndex);
40+
TypeInfoUtil util = new TypeInfoUtil(typeInfo);
41+
OaIdl.TYPEATTR attr = util.getTypeAttr();
42+
43+
for (int i = 0; i < attr.cFuncs.intValue(); i++) {
44+
OaIdl.FUNCDESC func = util.getFuncDesc(i);
45+
TypeInfoUtil.TypeInfoDoc funcDoc = util.getDocumentation(func.memid);
46+
System.out.println("Function " + i + ": " + funcDoc.getName() + " (cParams=" + func.cParams.shortValue() + ")");
47+
util.ReleaseFuncDesc(func);
48+
}
49+
}
50+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* Copyright (c) 2024 Lauri Ahonen, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32.COM;
25+
26+
import java.io.File;
27+
import java.util.Arrays;
28+
import java.util.HashSet;
29+
import java.util.Set;
30+
31+
import com.sun.jna.platform.win32.OaIdl.FUNCDESC;
32+
import com.sun.jna.platform.win32.OaIdl.TLIBATTR;
33+
import com.sun.jna.platform.win32.OaIdl.TYPEATTR;
34+
import com.sun.jna.platform.win32.OaIdl.VARDESC;
35+
36+
public class OaIdlRandomErrors {
37+
static Set<String> includedFilenames = new HashSet<>();
38+
39+
public static void main(String[] args) {
40+
String[] filenames = {"accessibilitycpl.dll", "activeds.tlb", "adprovider.dll", "amcompat.tlb", "apds.dll", "AppIdPolicyEngineApi.dll", "atl.dll", "atl100.dll", "atl110.dll", "AuditPolicyGPInterop.dll", "azroles.dll", "bcdsrv.dll", "capiprovider.dll", "catsrvut.dll", "cdosys.dll", "certcli.dll", "certenc.dll", "CertEnroll.dll", "certmgr.dll", "cic.dll", "clbcatq.dll", "cngprovider.dll", "comrepl.dll", "comsnap.dll", "comsvcs.dll", "connect.dll", "correngine.dll", "cryptext.dll", "DefaultPrinterProvider.dll", "DevicePairing.dll", "DevicePairingProxy.dll", "DfsShlEx.dll", "DiagCpl.dll", "dmocx.dll", "DMRServer.dll", "dnshc.dll", "dot3dlg.dll", "dot3hc.dll", "dpapiprovider.dll", "dskquota.dll", "dtsh.dll", "dxtmsft.dll", "dxtrans.dll", "EditionUpgradeHelper.dll", "EditionUpgradeManagerObj.dll", "EhStorAPI.dll", "EhStorShell.dll", "es.dll", "eventcls.dll", "expsrv.dll", "findnetprinters.dll", "FirewallAPI.dll", "FirewallControlPanel.dll", "fphc.dll", "FXSCOM.dll", "FXSCOMEX.dll", "gpprefcl.dll", "Groupinghc.dll", "HelpPaneProxy.dll", "hnetcfg.dll", "iasads.dll", "iasdatastore.dll", "iashlpr.dll", "iasnap.dll", "iasrad.dll", "iassam.dll", "iassdo.dll", "iassvcs.dll", "icsvc.dll", "ieframe.dll", "iepeers.dll", "igdDiag.dll", "imapi2.dll", "imapi2fs.dll", "inetcomm.dll", "InkEd.dll", "InkObjCore.dll", "ipnathlp.dll", "JavaScriptCollectionAgent.dll", "jscript.dll", "L2SecHC.dll", "LocationApi.dll", "MbaeApi.dll", "mmcndmgr.dll", "msaatext.dll", "msdatsrc.tlb", "msdtcuiu.dll", "msdxm.tlb", "msfeeds.dll", "msftedit.dll", "mshtml.tlb", "mshtmled.dll", "msi.dll", "msjtes40.dll", "MsraLegacy.tlb", "MsRdpWebAccess.dll", "mssitlb.dll", "mssrch.dll", "mstscax.dll", "msvbvm60.dll", "MSVidCtl.dll", "mswmdm.dll", "msxml3.dll", "msxml4.dll", "msxml6.dll", "mycomput.dll", "NaturalLanguage6.dll", "ndfapi.dll", "ndishc.dll", "netcenter.dll", "netcorehc.dll", "netprofm.dll", "NetworkCollectionAgent.dll", "nlahc.dll", "odbcconf.dll", "officecsp.dll", "oleacc.dll", "oleprn.dll", "pla.dll", "PNPXAssoc.dll", "PNPXAssocPrx.dll", "Pnrphc.dll", "PortableDeviceApi.dll", "PortableDeviceClassExtension.dll", "PortableDeviceConnectApi.dll", "PortableDeviceTypes.dll", "PrintConfig.dll", "printui.dll", "prnntfy.dll", "provcore.dll", "psisdecd.dll", "pstorec.dll", "puiapi.dll", "puiobj.dll", "qedit.dll", "quartz.dll", "rasdiag.dll", "rasgcw.dll", "rdpcorets.dll", "rdpencom.dll", "RdpRelayTransport.dll", "rdpsharercom.dll", "rdpviewerax.dll", "RegCtrl.dll", "rendezvousSession.tlb", "riched20.dll", "RoamingSecurity.dll", "RotMgr.dll", "scripto.dll", "scrobj.dll", "scrrun.dll", "sdiageng.dll", "sdohlp.dll", "Sens.dll", "shdocvw.dll", "shell32.dll", "shgina.dll", "signdrv.dll", "simpdata.tlb", "SMBHelperClass.dll", "SmiEngine.dll", "sppcomapi.dll", "sppwmi.dll", "SRH.dll", "srm.dll", "stclient.dll", "stdole2.tlb", "stdole32.tlb", "swprv.dll", "SysFxUI.dll", "TabbtnEx.dll", "tapi3.dll", "taskschd.dll", "termmgr.dll", "TransportDSA.dll", "TSWorkspace.dll", "tvratings.dll", "ucmhc.dll", "UIAnimation.dll", "UIAutomationCore.dll", "uicom.dll", "upnp.dll", "usbmon.dll", "VAN.dll", "vbscript.dll", "WaaSMedicPS.dll", "wavemsp.dll", "WfHC.dll", "wiaaut.dll", "wiascanprofiles.dll", "win32spl.dll", "wincredprovider.dll", "windowslivelogin.dll", "winethc.dll", "winhttpcom.dll", "WinMsoIrmProtector.dll", "WinOpcIrmProtector.dll", "WinSATAPI.dll", "wisp.dll", "wkspbrokerAx.dll", "WLanConn.dll", "wlandlg.dll", "WLanHC.dll", "wlanpref.dll", "wlanui.dll", "wlidcli.dll", "wlidprov.dll", "wmdmlog.dll", "WMNetMgr.dll", "wmp.dll", "wmpdxm.dll", "wmpshell.dll", "WorkFoldersShell.dll", "workfolderssvc.dll", "WPDSp.dll", "wscapi.dll", "wshcon.dll", "wshext.dll", "WsmAuto.dll", "wuapi.dll", "wvc.dll", "WWanAPI.dll", "WWanHC.dll", "xwizards.dll", "xwreg.dll", "xwtpdui.dll", "xwtpw32.dll"};
41+
includedFilenames.addAll(Arrays.asList(filenames));
42+
processDir(new File("C:\\Windows\\System32"));
43+
processDir(new File("C:\\Windows\\SysWOW64"));
44+
System.out.println("Finished.");
45+
}
46+
47+
protected static void processDir(File dir) {
48+
for (File file : dir.listFiles()) {
49+
if (includedFilenames.contains(file.getName())) {
50+
processFile(file);
51+
}
52+
}
53+
}
54+
55+
protected static void processFile(File file) {
56+
try {
57+
System.out.println(file);
58+
TypeLibUtil libUtil = new TypeLibUtil(file.toString());
59+
60+
// Lib attributes
61+
TLIBATTR libAttr = libUtil.getLibAttr();
62+
libUtil.ReleaseTLibAttr(libAttr);
63+
64+
// Types
65+
int count = libUtil.getTypeInfoCount();
66+
System.out.println("Type count: " + count);
67+
for (int i = 0; i < count; i++) {
68+
TypeInfoUtil typeUtil = libUtil.getTypeInfoUtil(i);
69+
70+
// Type attributes
71+
TYPEATTR typeAttr = typeUtil.getTypeAttr();
72+
typeUtil.ReleaseTypeAttr(typeAttr);
73+
74+
// Functions
75+
for (int j = 0; j < typeAttr.cFuncs.intValue(); j++) {
76+
FUNCDESC funcDesc = typeUtil.getFuncDesc(j);
77+
typeUtil.ReleaseFuncDesc(funcDesc);
78+
}
79+
80+
// Variables
81+
for (int j = 0; j < typeAttr.cVars.intValue(); j++) {
82+
VARDESC varDesc = typeUtil.getVarDesc(j);
83+
typeUtil.ReleaseVarDesc(varDesc);
84+
}
85+
}
86+
87+
libUtil.getTypelib().Release();
88+
89+
} catch (Throwable e) {
90+
e.printStackTrace(System.out);
91+
}
92+
}
93+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* Copyright (c) 2024 Lauri Ahonen, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32.COM;
25+
26+
import com.sun.jna.platform.win32.OaIdl;
27+
28+
public class VarDescBug {
29+
30+
public static void main(String[] args){
31+
TypeLibUtil libUtil = new TypeLibUtil("C:\\Windows\\System32\\stdole2.tlb");
32+
int count = libUtil.getTypeInfoCount();
33+
for (int i = 0; i < count; i++) {
34+
TypeInfoUtil infoUtil = new TypeInfoUtil(libUtil.getTypeInfo(i));
35+
OaIdl.TYPEATTR attr = infoUtil.getTypeAttr();
36+
for (int j = 0; j < attr.cVars.intValue(); j++) {
37+
try {
38+
infoUtil.getVarDesc(j);
39+
} catch (Exception e) {
40+
System.out.println("ERROR:" + e);
41+
}
42+
}
43+
}
44+
}
45+
46+
}

0 commit comments

Comments
 (0)