PORTWRITEARRAY is defined to input an array of small numbers.
If you pass it an array of values that aren't numbers, it doesn't throw a bad input
error, but instead writes some random value in place of the number.
The bug is bad input checking in lportwritearray
// fill buffer with elements of the array
for (int i = 0; i < count; i++)
{
NODE * item = litem(cons_list(make_intnode(i + getarrorg(obj)), obj));
txbuffer[i] = getint(cnv_node_to_numnode(item));
}
Here, cnv_node_to_numnode returns Unbound for any NODE that cannot be converted to a number and a FLOATINGPOINT for floating-point numbers. getint() does not check the type and returns whatever is at the memory offset where a numeric node would store an integer. For Unbound this memory is unitialized. For a FLOATINGPOINT, it's some part of the floating point in IEEE format.
This is reproducible in MSWLogo 6.5b and all version of FMSLogo up through 7.2.0.
Throwing a bad input error might have too much risk for breaking backward-compatibility, since old buggy programs might expect PORTWRITEARRAY to work when given bad input. Similarly, silently removing the bad input from the data stream might cause problems for old buggy programs which expect PORTWRITEARRAY write something.
The most compatible fix is to write a 0 byte.
Note that I don't expect any new programs to be written using PORTWRITEARRAY, so fixing this is mostly to make it easier to write automated tests.
How Reproducible:
Every Time
Steps to Reproduce:
1) Connect a null modem from COM4 to COM5. This can be accomplished in software using an emulator called com0com.
2) Start an instance of FMSLogo and run this
PORTOPEN "com4
3) Start a second instance of FMSLogo, specifying a file name so that a second instance opens (instead of giving focus to the first instance). Run this
PORTOPEN "com5
IGNORE PORTWRITEARRAY 4 {123.45 "bad {0} [1] }
4) On the first instance, run
SHOW (LIST PORTREADCHAR PORTREADCHAR PORTREADCHAR PORTREADCHAR)
What Happens:
The first instance prints [77 0 0 0].
The 77 should be printed every time, but the rest depends on uninitialize memory.
For example, if I run:
REPEAT 1000 [ IGNORE WORD "SOME "TEXT ]
In the second instance before running the PORTWRITEARRAY instruction, then the first instance prints [77 90 90 90]
Expected Result:
The first instance prints [0 0 0 0]
I have committed [r4565] as a fix. This fix will be available in FMSLogo 7.3.0.
I decided to write an ASCII space, instead of an ASCII NUL, when given bad input. For the protocols which use a serial port, this is the least likely to cause compatibility problems.
Related
Commit: [r4565]