Question

I'm seeing some strange behaviour when making a change to the following VB.net code. This is the original sourcecode:

Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
    Dim possiblePurposes As New InfoCollector.Purpose
    Dim isPurposeValid As Boolean = False

    'Any of the following purposes (but only these)
    'should be considered valid
    Select Case UCase(purposeId)
        Case UCase(possiblePurposes.FirstPurpose), _
             UCase(possiblePurposes.SecondPurpose), _
             UCase(possiblePurposes.ThirdPurpose), _
             UCase(possiblePurposes.FourthPurpose)

                isPurposeValid = True
            Case Else
                isPurposeValid = False
        End Select

        Return isPurposeValid
End Function

This is the new version. The only change is the addition of a fifth valid purpose:

Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
    Dim possiblePurposes As New InfoCollector.Purpose
    Dim isPurposeValid As Boolean = False

        Select Case UCase(purposeId)
            Case UCase(possiblePurposes.FirstPurpose), _
             UCase(possiblePurposes.SecondPurpose), _
             UCase(possiblePurposes.ThirdPurpose), _
             UCase(possiblePurposes.FourthPurpose), _
             UCase(possiblePurposes.FifthPurpose) 

                isPurposeValid = True
            Case Else
                isPurposeValid = False
        End Select

        Return isPurposeValid
End Function

I compiled this new version on my local PC and tested the functionality, and it worked fine. After checking this into our central code repository, and building it on the server however, the usage failed (it appeared to be ignoring the new purpose). While trying to figure out what is missing, I decompiled the .DLL found on the server, and this is what it gave me (Note: I've changed the variable names and reformatted slightly):

Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean 
    Dim ValidateSelectedId As Boolean
    Dim possiblePurposes As Purpose = New Purpose()
    Dim isPurposeValid As Boolean = False
    Dim str As String = Strings.UCase(purposeId)

    If (Operators.CompareString(str, Strings.UCase(possiblePurposes.FirstPurpose), False) <> 0) Then
        If (Operators.CompareString(str, Strings.UCase(possiblePurposes.SecondPurpose), False) <> 0 
            AndAlso (Operators.CompareString(str, Strings.UCase(possiblePurposes.ThirdPurpose), False) = 0 
            OrElse Operators.CompareString(str, Strings.UCase(possiblePurposes.FourthPurpose), False) <> 0)) Then

                If (Operators.CompareString(str, Strings.UCase(possiblePurposes.FifthPurpose), False) = 0) Then
                    Return True
                End If

                isPurposeValid = False
        End If
    End If

    Return isPurposeValid
End Function

I also tried decompiling this into C#, which might be a little easier to read for some of us:

private bool ValidateSelectedId(string purposeId)
{
    bool ValidateSelectedId;
    Purpose possiblePurposes = new Purpose();
    bool isPurposeValid = false;
    string str = Strings.UCase(purposeId);

    if (Operators.CompareString(str, Strings.UCase(possiblePurposes.FirstPurpose), false) != 0)
    {
        if (Operators.CompareString(str, Strings.UCase(possiblePurposes.SecondPurpose), false) != 0 
            && (Operators.CompareString(str, Strings.UCase(possiblePurposes.ThirdPurpose), false) == 0 
            || Operators.CompareString(str, Strings.UCase(possiblePurposes.FourthPurpose), false) != 0))
        {
            if (Operators.CompareString(str, Strings.UCase(possiblePurposes.FifthPurpose), false) == 0)
            {
                return true;
            }
            isPurposeValid = false;
        }
    }
    return isPurposeValid;
}

This however, seems to be doing something like the inverse of what I wanted, and not at all what the original source code is saying!

I can't see how the original source code could have been compiled to this. Could there be something wrong with my decompiler (I'm using Just Decompile from Telerik)? If so, how come the logic works on my local PC, but not on the server?

Could there actually be some kind of bug in the compile-process? Or am I being a complete Id**t, and simply misunderstanding the logic in the decompiled code?

Any relevant theories to explain this will be greatly appreciated.

Was it helpful?

Solution

Silly me.
I eventually discovered the reason this did not work on the server: There was another related bug which had been fixed locally, but not on the server.

Silly decompiler.
I was confused by the result from the decompiler, which was obviously messed up. I've used JustDecompile many times before, but never run across a problem like this. Apparently, it is unable to decompile the code from the above method in any reasonable fashion.

My assumptions are that some form of optimization is done during compilation, which JustDecompile has trouble understanding and displaying properly.

I just wanted to verify that my changes had been published to the server. Instead I was sent on a wild goose chase for a phantom bug. Lesson learned: Use the decompiler when needed, but do not automatically trust everything it tells you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top