« The Answer | Main | Strange Article on Slashdot »

August 25, 2005

Find the Bug in this "Virus"

I was looking at the code for the alleged Monad viruses, which I discussed here and has been kicked around elsewhere. This is the first of the five, that simply copies itself on top of every other .msh file in the same directory. This is the verbatim code from RRLF:

$name_array=get-childitem *.msh
foreach ($name in $name_array)
  if ($name.Length -eq 249)

foreach ($victim in $name_array)
  if ($name.Length -ne 249)
    copy-item $my_file $name.Name

So I was looking at this code and I noticed that it had a bug in it!! In fact it's precisely the kind of bugs I have in Find the Bug...it's a short snippet of code, that looks reasonable and is syntactically correct, but it doesn't work as expected. It even fits nicely into the bug type classification scheme...but I won't reveal the type since that makes it easier to spot.

Can you find the bug? Can you explain in which situations it would manifest itself, and how it would cause the program to behave?

Incidentally on the virus scare itself, Terry Myerson, GM of Exchange Server, has a good post that talks about the quote-unquote virus, but also gives a glimpse into the power of Monad/Exchange integration.

Posted by AdamBa at August 25, 2005 02:33 PM

Trackback Pings

TrackBack URL for this entry:


doesn't get-childitem return null when there are no records?

Posted by: David B Banister at August 25, 2005 03:39 PM

The second loop is using the loop variable of the first loop. name should be victim. So when there is only one file (its self), it will do nothing, when there is more than one file it will only overwrite the last??

Posted by: Simeon at August 25, 2005 03:51 PM

What Simeon said.

Posted by: Edward at August 25, 2005 04:20 PM

(What Simeon said) +

Even when there are multiple files,

copy-item $my_file $name.Name

doesnt do much since $my_file is the same as $name.Name.

Posted by: john k at August 25, 2005 05:42 PM

"Even when there are multiple files,

copy-item $my_file $name.Name

doesnt do much since $my_file is the same as $name.Name."

Only when my_file is the last file visited by the top loop.

If you think of files a, b, c, d in the case of d been the 249 byte file then nothing would happen, but if c is the 249 file then d will be replaced four times. Even worse (not sure if it can happen) is if none of the files are the 249 file. Then $my_file is undefiend.

Posted by: Simeon at August 25, 2005 08:40 PM

Not bad, you saw the bug (the code uses $name instead of $victim inside the second loop), but nobody has precisely stated the situations in which the code would not perform as expected.

Note that the script itself is 249 bytes...and the assumption is it already exists in the current directory (so it will be included in $name_array). The program does have a logical flaw that it assumes it is the one and only 249-byte file in the directory, but let's ignore that for now.

David, get-childitem does return $null when there are no files, but that's fine, the foreach loops will then do nothing (although per the previous paragraph the script assumes that itself, at least, is present in the directory).

- adam

Posted by: Adam Barr at August 25, 2005 09:36 PM

Well, the first thing I noticed was the lines with the length checks of 249. No idea what this length check was for, but in my experience, just checking for eq or neq to some constant value is all too often wrong - what happens if, or should I say, when, it changes?

There's also no check that the length is not zero, which might be something to deal with before attempting tyhe copy ( a zero length file might be open thus causing an error in the script you're not catching).

The bugs your other commentators mention are also clear after studying the code for a bit.

Posted by: Thomas Lee at August 26, 2005 03:48 AM

"Not bad, you saw the bug, but nobody has precisely stated the situations in which the code would not perform as expected."

I was more of thinking … the only situation the code works correctly is when there is two files, the first returned by "get-childitem" been the virus, and the second been a target file.

As I see the bug, the code will not work correctly when there is more than two files present, because only the last of the target files will be replaced. Also when the last file returned by "get-chidlitem" is the virus, no files will be altered.

Is that enough information?

Posted by: Simeon at August 29, 2005 09:19 PM

Simeon: Yes, I agree with your analysis. Nice work.

Posted by: Adam Barr at September 1, 2005 10:21 PM