Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The weirdest VBA issue I have ever seen (VBASigned Possible Bug on Boolean Condition)

Tags:

ms-word

excel

vba

In MS Word I added some code to see if a document is missing its digital signature, or at least I thought I did. I've decided to share before testing this on other systems.

Sub test()
    If Not ThisDocument.VBASigned Then
        Debug.Print "I am NOT signed"
    End If
End Sub

Problem: The code above produces the same result irrespective of whether or not the document has a digital signature. If I modify the code by removing the Not I still get unexpected results.

I've tried to coerce things by doing things like:

If Not CBool(ThisDocument.VBASigned) Then

But more surprisingly, the following code also fails:

Sub test()
    Dim isSigned As Boolean
    isSigned = ThisDocument.VBASigned

    If Not isSigned Then
        Debug.Print "I am NOT signed"
    End If
End Sub

Even though ThisDocument.VBASigned AND isSigned are both TRUE...
snapshot of my code running but if change isSigned = ThisDocument.VBASigned to isSigned = True then everything works as expected.

Can anyone confirm this? Any thoughts?


Edits below answer some of the questions:

  1. Yes, using Option Explicit, Yes also tried Debug.
    This code:

    Option Explicit
    
    Sub test()
        Dim isSigned As Boolean
        isSigned = ThisDocument.VBASigned
        Debug.Print ThisDocument.VBASigned
        If Not isSigned Then
            Debug.Print "I am NOT signed"
        End If
    End Sub
    

    Produces this output:

    True
    I am NOT signed

  2. Testing: True * 0 - 1.

    Sub test()
        Dim isSigned As Boolean
        isSigned = ThisDocument.VBASigned
        Debug.Print ThisDocument.VBASigned
        If Not (isSigned * 0 - 1) Then
            Debug.Print "I am NOT signed"
        End If
    End Sub
    

    Produces this (expected) output:

    True


Edit: interesting article by Raymond Chen that might provide some further insights as to how this happened: https://blogs.msdn.microsoft.com/oldnewthing/20041222-00/?p=36923

In short, as the Windows operating system evolved it included different types of booleans: int > byte > variant

like image 651
SlowLearner Avatar asked May 10 '17 03:05

SlowLearner


2 Answers

After playing with a digitally signed version of a document that SlowLearner supplied me, I have determined that Word's VBASigned is returning a 1 when it is signed.

This then leads to problems in the If statement, because Not 1 is equal to -2, and Not 0 is equal to -1 - thus leading to Not VBASigned returning a non-zero (i.e. non-False) value in all cases.


The MSDN documentation states that VBASigned is a read-only Boolean, and the type of variable returned has been confirmed (by TypeName(ThisDocument.VBASigned)) to be Boolean, but it appears it should be treated as a numeric value instead.


An additional interesting fact is that CBool(ThisDocument.VBASigned) * 1 gives an answer of 1, while a CBool(1) * 1 gives an answer of -1. So it seems that, when VBA decides that a value is already a Boolean (such as ThisDocument.VBASigned is meant to be), it doesn't bother to do any conversions. But, when the parameter to CBool is not a Boolean, it converts a non-zero value to be -1.


Code that would work:

Sub test()
    Dim myVBASigned As Integer
    Dim isSigned As Boolean
    myVBASigned = ThisDocument.VBASigned 'Store as Integer
    isSigned = myVBASigned               'Convert to a "true" Boolean

    If Not isSigned Then                 'Use the "true" Boolean
        Debug.Print "I am NOT signed"
    End If

End Sub
like image 190
YowE3K Avatar answered Oct 18 '22 19:10

YowE3K


Testing this against Excel show that this is a bug in Word.

Assuming we have new documents with VBA enabled and VBA signed:

Using in Excel:

Sub testExcel()
    Dim isSigned As Boolean
    isSigned = ThisWorkbook.VBASigned
    Debug.Print ThisWorkbook.VBASigned
    If Not isSigned Then
        Debug.Print "I am NOT signed"
    Else
        Debug.Print "I AM signed"
    End If
End Sub

Results in

True
I AM signed

But using the same in Word

Sub testWord()
    Dim isSigned As Boolean
    isSigned = ThisDocument.VBASigned
    Debug.Print ThisDocument.VBASigned
    If Not isSigned Then
        Debug.Print "I am NOT signed"
    Else
        Debug.Print "I AM signed"
    End If
End Sub

Results in

True
I am NOT signed

This clearly shows that there is a bug in Word.


This was tested with

  • Windows 10 x64
  • Office Professional Plus 2016
    • Version 1703 Build 7967.2139
    • German
    • 64 Bit Office
like image 26
Pᴇʜ Avatar answered Oct 18 '22 19:10

Pᴇʜ