From a5aba329c9fb975edbdb7f1650489e525a2b5ecc Mon Sep 17 00:00:00 2001
From: clay_shooter <>
Date: Mon, 8 Nov 2010 02:48:56 +0000
Subject: [PATCH] SF3065265 Bit masking in Variant.getXXXRef() uses wrong mask
allowing more than one type to be seen as the requested type. Code that
passed in the correct type always worked but invalid types were not always
detected.
---
jacob/docs/ReleaseNotes.html | 16 ++++---
jacob/src/com/jacob/com/Variant.java | 44 ++++++++++---------
jacob/src/com/jacob/com/VariantUtilities.java | 2 +-
jacob/unittest/com/jacob/com/VariantTest.java | 37 ++++++++++++++++
4 files changed, 73 insertions(+), 26 deletions(-)
diff --git a/jacob/docs/ReleaseNotes.html b/jacob/docs/ReleaseNotes.html
index a8a2313..e220cbe 100644
--- a/jacob/docs/ReleaseNotes.html
+++ b/jacob/docs/ReleaseNotes.html
@@ -16,6 +16,17 @@
Tracked Changes
Bugs |
+
+ 3065265 |
+ Bit masking in Variant.getXXXRef() uses wrong mask allowing more than
+ one type to be seen as the requested type. Code that passed in the correct type always worked
+ but invalid types were not always detected.(M4) |
+
+
+ 2935662 |
+ Error handling code crashes because of uninitialized data in Dispatch.cpp
+ Check for NULL fails. pfnDeferredFillIn pointer is not initialized, but it's not NULL.(M4) |
+
2819445 |
SafeArray.fromLongArray fails when using VariantLongInt (M3) |
@@ -32,11 +43,6 @@ Tracked Changes
checked on every object creation for users who run in the standard
all classes in ROT mode. (M2)
-
- 2935662 |
- Error handling code crashes because of uninitialized data in Dispatch.cpp
- Check for NULL fails. pfnDeferredFillIn pointer is not initialized, but it's not NULL. |
-
|
|
diff --git a/jacob/src/com/jacob/com/Variant.java b/jacob/src/com/jacob/com/Variant.java
index 02de337..91ae210 100644
--- a/jacob/src/com/jacob/com/Variant.java
+++ b/jacob/src/com/jacob/com/Variant.java
@@ -137,13 +137,13 @@ public class Variant extends JacobObject {
// VT_CARRARY = 28
// VT_USERDEFINED = 29
- /** what is this? VT_TYPEMASK && VT_BSTR_BLOB */
+ /** what is this? VT_TYPEMASK && VT_BSTR_BLOB 0xfff */
public static final short VariantTypeMask = 4095;
- /** variant's type is array VT_ARRAY */
+ /** variant's type is array VT_ARRAY 0x2000 */
public static final short VariantArray = 8192;
- /** variant's type is a reference (to IDispatch?) VT_BYREF */
+ /** variant's type is a reference (to IDispatch?) VT_BYREF 0x4000 */
public static final short VariantByref = 16384;
/*
@@ -289,6 +289,7 @@ public Variant changeType(short in) {
*
* @return ?? comment says null?
*/
+ @Override
public native Object clone();
/**
@@ -303,6 +304,7 @@ public Variant changeType(short in) {
*
* @see java.lang.Object#finalize()
*/
+ @Override
protected void finalize() {
safeRelease();
}
@@ -331,7 +333,7 @@ public boolean getBoolean() {
* if variant is not of the requested type
*/
public boolean getBooleanRef() {
- if ((this.getvt() & VariantBoolean) == VariantBoolean
+ if ((this.getvt() & VariantTypeMask) == VariantBoolean
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantBooleanRef();
} else {
@@ -365,7 +367,7 @@ public byte getByte() {
* if variant is not of the requested type
*/
public byte getByteRef() {
- if ((this.getvt() & VariantByte) == VariantByte
+ if ((this.getvt() & VariantTypeMask) == VariantByte
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantByteRef();
} else {
@@ -404,7 +406,7 @@ public Currency getCurrency() {
* if variant is not of the requested type
*/
public Currency getCurrencyRef() {
- if ((this.getvt() & VariantCurrency) == VariantCurrency
+ if ((this.getvt() & VariantTypeMask) == VariantCurrency
&& (this.getvt() & VariantByref) == VariantByref) {
return new Currency(getVariantCurrencyRef());
} else {
@@ -438,7 +440,7 @@ public double getDate() {
* if variant is not of the requested type
*/
public double getDateRef() {
- if ((this.getvt() & VariantDate) == VariantDate
+ if ((this.getvt() & VariantTypeMask) == VariantDate
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantDateRef();
} else {
@@ -473,7 +475,7 @@ public BigDecimal getDecimal() {
* if variant is not of the requested type
*/
public BigDecimal getDecimalRef() {
- if ((this.getvt() & VariantDecimal) == VariantDecimal
+ if ((this.getvt() & VariantTypeMask) == VariantDecimal
&& (this.getvt() & VariantByref) == VariantByref) {
return (BigDecimal) (getVariantDecRef());
} else {
@@ -493,7 +495,7 @@ public BigDecimal getDecimalRef() {
* if wrong variant type
*/
public Dispatch getDispatch() {
- if ((this.getvt() & VariantDispatch) == VariantDispatch) {
+ if (this.getvt() == VariantDispatch) {
return toDispatch();
} else {
throw new IllegalStateException(
@@ -511,7 +513,7 @@ public Dispatch getDispatch() {
* if variant is not of the requested type
*/
public Dispatch getDispatchRef() {
- if ((this.getvt() & VariantDispatch) == VariantDispatch
+ if ((this.getvt() & VariantTypeMask) == VariantDispatch
&& (this.getvt() & VariantByref) == VariantByref) {
return toDispatch();
} else {
@@ -544,7 +546,7 @@ public double getDouble() {
* if variant is not of the requested type
*/
public double getDoubleRef() {
- if ((this.getvt() & VariantDouble) == VariantDouble
+ if ((this.getvt() & VariantTypeMask) == VariantDouble
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantDoubleRef();
} else {
@@ -589,7 +591,7 @@ public int getError() {
* if variant is not of the requested type
*/
public int getErrorRef() {
- if ((this.getvt() & VariantError) == VariantError
+ if ((this.getvt() & VariantTypeMask) == VariantError
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantErrorRef();
} else {
@@ -621,7 +623,7 @@ public float getFloat() {
* if variant is not of the requested type
*/
public float getFloatRef() {
- if ((this.getvt() & VariantFloat) == VariantFloat
+ if ((this.getvt() & VariantTypeMask) == VariantFloat
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantFloatRef();
} else {
@@ -659,7 +661,7 @@ public int getInt() {
* if variant is not of the requested type
*/
public int getIntRef() {
- if ((this.getvt() & VariantInt) == VariantInt
+ if ((this.getvt() & VariantTypeMask) == VariantInt
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantIntRef();
} else {
@@ -735,7 +737,7 @@ public long getLong() {
* if variant is not of the requested type
*/
public long getLongRef() {
- if ((this.getvt() & VariantLongInt) == VariantLongInt
+ if ((this.getvt() & VariantTypeMask) == VariantLongInt
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantLongRef();
} else {
@@ -781,7 +783,7 @@ public short getShort() {
* if variant is not of the requested type
*/
public short getShortRef() {
- if ((this.getvt() & VariantShort) == VariantShort
+ if ((this.getvt() & VariantTypeMask) == VariantShort
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantShortRef();
} else {
@@ -815,7 +817,7 @@ public String getString() {
* if variant is not of the requested type
*/
public String getStringRef() {
- if ((this.getvt() & VariantString) == VariantString
+ if ((this.getvt() & VariantTypeMask) == VariantString
&& (this.getvt() & VariantByref) == VariantByref) {
return getVariantStringRef();
} else {
@@ -834,7 +836,7 @@ public String getStringRef() {
* Variant
*/
public Object getVariant() {
- if ((this.getvt() & VariantVariant) == VariantVariant
+ if ((this.getvt() & VariantTypeMask) == VariantVariant
&& (this.getvt() & VariantByref) == VariantByref) {
if (JacobObject.isDebugEnabled()) {
JacobObject.debug("About to call getVariantVariant()");
@@ -1607,8 +1609,8 @@ public void putStringRef(String in) {
* A object that is to be referenced by this variant. If
* objectToBeWrapped is already of type Variant, then it is used.
* If objectToBeWrapped is not Variant then
- * new Variant(objectToBeWrapped)
is called and
- * the result is passed into the com layer
+ * new Variant(objectToBeWrapped)
is called and the
+ * result is passed into the com layer
* @throws IllegalArgumentException
* if inVariant = null or if inVariant is a Varint
*/
@@ -1874,6 +1876,7 @@ private native void putVariantDecRef(int signum, byte scale, int lo,
*
* @see com.jacob.com.JacobObject#safeRelease()
*/
+ @Override
public void safeRelease() {
// The well known constants should not be released.
// Unfortunately this doesn't fix any other classes that are
@@ -2161,6 +2164,7 @@ public short toShort() {
* @throws IllegalStateException
* if there is no underlying windows data structure
*/
+ @Override
public String toString() {
try {
// see if we are in a legal state
diff --git a/jacob/src/com/jacob/com/VariantUtilities.java b/jacob/src/com/jacob/com/VariantUtilities.java
index afaa8bb..1ac652a 100644
--- a/jacob/src/com/jacob/com/VariantUtilities.java
+++ b/jacob/src/com/jacob/com/VariantUtilities.java
@@ -356,7 +356,7 @@ protected static Object variantToObject(Variant sourceData) {
break;
case Variant.VariantTypeMask: // 4095
result = new NotImplementedException(
- "toJavaObject() Not implemented for VariantTypeMask");
+ "toJavaObject() Not implemented for VariantBstrBlob/VariantTypeMask");
break;
case Variant.VariantArray: // 8192
result = new NotImplementedException(
diff --git a/jacob/unittest/com/jacob/com/VariantTest.java b/jacob/unittest/com/jacob/com/VariantTest.java
index ac09e21..2f4c0ba 100644
--- a/jacob/unittest/com/jacob/com/VariantTest.java
+++ b/jacob/unittest/com/jacob/com/VariantTest.java
@@ -648,6 +648,7 @@ public boolean isComplete() {
*
* @see java.lang.Runnable#run()
*/
+ @Override
public void run() {
for (int variantIndex = 0; variantIndex < initialRunSize; variantIndex++) {
try {
@@ -664,4 +665,40 @@ public void run() {
isComplete = true;
}
}
+
+ /**
+ * there was a bitwise masking error that let booleans be seen as dispatch
+ * objects Bug Report SF3065265
+ */
+ public void testGetDispatch() {
+ Variant testVariant = new Variant();
+ testVariant.putBooleanRef(true);
+ try {
+ // throws IllegalStateException if Jacob detects the type
+ // throws some other bad exception if COM blows up failing the
+ // conversion
+ testVariant.getDispatchRef();
+ fail("Should not have converted boolean to dispatch");
+ } catch (IllegalStateException e) {
+ // yeah! can't get dispatch from boolean
+ }
+ }
+
+ /**
+ * there was a bitwise masking error that let booleans be seen as dispatch
+ * objects Bug Report SF3065265
+ */
+ public void testGetError() {
+ Variant testVariant = new Variant();
+ testVariant.putErrorRef(3);
+ try {
+ // throws IllegalStateException if Jacob detects the type
+ // throws some other bad exception if COM blows up failing the
+ // conversion
+ testVariant.getStringRef();
+ fail("Should not have converted error to string");
+ } catch (IllegalStateException e) {
+ // yeah! can't get dispatch from boolean
+ }
+ }
}