Skip to content

Commit 48560fd

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 48560fd

File tree

4 files changed

+203
-15
lines changed

4 files changed

+203
-15
lines changed

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

Lines changed: 83 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,44 @@ 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[]{"memid", "lprgscode", "funckind", "invkind",
1339+
"callconv", "cParamsOpt", "oVft", "cScodes", "elemdescFunc", "wFuncFlags"}) {
1340+
readField(field);
1341+
}
13191342

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

@@ -1398,14 +1440,10 @@ public static class ByReference extends _VARDESC implements
13981440
public VARIANT.ByReference lpvarValue;
13991441

14001442
public _VARDESC() {
1401-
setType("lpvarValue");
1402-
this.read();
14031443
}
14041444

14051445
public _VARDESC(Pointer pointer) {
14061446
super(pointer);
1407-
setType("lpvarValue");
1408-
this.read();
14091447
}
14101448

14111449
/**
@@ -1431,9 +1469,17 @@ public VARDESC() {
14311469

14321470
public VARDESC(Pointer pointer) {
14331471
super(pointer);
1434-
this._vardesc.setType("lpvarValue");
14351472
this.read();
14361473
}
1474+
1475+
@Override
1476+
public void read() {
1477+
readField("varkind");
1478+
if (_vardesc != null) {
1479+
_vardesc.setType(varkind.value == VARKIND.VAR_CONST ? "lpvarValue" : "oInst");
1480+
}
1481+
super.read();
1482+
}
14371483
}
14381484

14391485
@FieldOrder({"tdesc", "_elemdesc"})
@@ -1654,14 +1700,10 @@ public static class _TYPEDESC extends Union {
16541700
public HREFTYPE hreftype;
16551701

16561702
public _TYPEDESC() {
1657-
this.setType("hreftype");
1658-
this.read();
16591703
}
16601704

16611705
public _TYPEDESC(Pointer pointer) {
16621706
super(pointer);
1663-
this.setType("hreftype");
1664-
this.read();
16651707
}
16661708

16671709
public TYPEDESC.ByReference getLptdesc() {
@@ -1687,18 +1729,44 @@ public HREFTYPE getHreftype() {
16871729
public VARTYPE vt;
16881730

16891731
public TYPEDESC() {
1690-
this.read();
16911732
}
16921733

16931734
public TYPEDESC(Pointer pointer) {
16941735
super(pointer);
1695-
this.read();
16961736
}
16971737

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

17041772
@FieldOrder({"dwReserved", "wIDLFlags"})
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.sun.jna.platform.win32.COM;
2+
3+
import com.sun.jna.platform.win32.OaIdl;
4+
5+
/**
6+
* Test for TYPEDESC and FUNCDESC union handling.
7+
* This test iterates through functions in a Shell32 type library interface
8+
* and verifies that JNA correctly reads the discriminated unions in TYPEDESC
9+
* and handles the lprgelemdescParam array correctly when cParams=0.
10+
*/
11+
public class InvalidMemoryAccessBug {
12+
public static void main(String[] args) {
13+
TypeLibUtil libUtil = new TypeLibUtil("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}", 1, 0); // C:\Windows\SysWOW64\shell32.dll
14+
int typeIndex = 21;
15+
16+
ITypeInfo typeInfo = libUtil.getTypeInfo(typeIndex);
17+
TypeInfoUtil util = new TypeInfoUtil(typeInfo);
18+
OaIdl.TYPEATTR attr = util.getTypeAttr();
19+
20+
for (int i = 0; i < attr.cFuncs.intValue(); i++) {
21+
OaIdl.FUNCDESC func = util.getFuncDesc(i);
22+
TypeInfoUtil.TypeInfoDoc funcDoc = util.getDocumentation(func.memid);
23+
System.out.println("Function " + i + ": " + funcDoc.getName() + " (cParams=" + func.cParams.shortValue() + ")");
24+
util.ReleaseFuncDesc(func);
25+
}
26+
}
27+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.sun.jna.platform.win32.COM;
2+
3+
import java.io.File;
4+
import java.util.Arrays;
5+
import java.util.HashSet;
6+
import java.util.Set;
7+
8+
import com.sun.jna.platform.win32.OaIdl.FUNCDESC;
9+
import com.sun.jna.platform.win32.OaIdl.TLIBATTR;
10+
import com.sun.jna.platform.win32.OaIdl.TYPEATTR;
11+
import com.sun.jna.platform.win32.OaIdl.VARDESC;
12+
13+
public class OaIdlRandomErrors {
14+
static Set<String> includedFilenames = new HashSet<>();
15+
16+
public static void main(String[] args) {
17+
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"};
18+
includedFilenames.addAll(Arrays.asList(filenames));
19+
processDir(new File("C:\\Windows\\System32"));
20+
processDir(new File("C:\\Windows\\SysWOW64"));
21+
System.out.println("Finished.");
22+
}
23+
24+
protected static void processDir(File dir) {
25+
for (File file : dir.listFiles()) {
26+
if (includedFilenames.contains(file.getName())) {
27+
processFile(file);
28+
}
29+
}
30+
}
31+
32+
protected static void processFile(File file) {
33+
try {
34+
System.out.println(file);
35+
TypeLibUtil libUtil = new TypeLibUtil(file.toString());
36+
37+
// Lib attributes
38+
TLIBATTR libAttr = libUtil.getLibAttr();
39+
libUtil.ReleaseTLibAttr(libAttr);
40+
41+
// Types
42+
int count = libUtil.getTypeInfoCount();
43+
System.out.println("Type count: " + count);
44+
for (int i = 0; i < count; i++) {
45+
TypeInfoUtil typeUtil = libUtil.getTypeInfoUtil(i);
46+
47+
// Type attributes
48+
TYPEATTR typeAttr = typeUtil.getTypeAttr();
49+
typeUtil.ReleaseTypeAttr(typeAttr);
50+
51+
// Functions
52+
for (int j = 0; j < typeAttr.cFuncs.intValue(); j++) {
53+
FUNCDESC funcDesc = typeUtil.getFuncDesc(j);
54+
typeUtil.ReleaseFuncDesc(funcDesc);
55+
}
56+
57+
// Variables
58+
for (int j = 0; j < typeAttr.cVars.intValue(); j++) {
59+
VARDESC varDesc = typeUtil.getVarDesc(j);
60+
typeUtil.ReleaseVarDesc(varDesc);
61+
}
62+
}
63+
64+
libUtil.getTypelib().Release();
65+
66+
} catch (Throwable e) {
67+
e.printStackTrace(System.out);
68+
}
69+
}
70+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.sun.jna.platform.win32.COM;
2+
3+
import com.sun.jna.platform.win32.OaIdl;
4+
5+
public class VarDescBug {
6+
7+
public static void main(String[] args){
8+
TypeLibUtil libUtil = new TypeLibUtil("C:\\Windows\\System32\\stdole2.tlb");
9+
int count = libUtil.getTypeInfoCount();
10+
for (int i = 0; i < count; i++) {
11+
TypeInfoUtil infoUtil = new TypeInfoUtil(libUtil.getTypeInfo(i));
12+
OaIdl.TYPEATTR attr = infoUtil.getTypeAttr();
13+
for (int j = 0; j < attr.cVars.intValue(); j++) {
14+
try {
15+
infoUtil.getVarDesc(j);
16+
} catch (Exception e) {
17+
System.out.println("ERROR:" + e);
18+
}
19+
}
20+
}
21+
}
22+
23+
}

0 commit comments

Comments
 (0)