[DLLCC] Silent truncation of out of bounds Integers

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[DLLCC] Silent truncation of out of bounds Integers

Joachim Geidel
Hi all,

while I was working on the VisualWorks version of JNIPort, a Smalltalk
interface to Java, several unit tests of JNIPort failed because they
expected Errors when using Integer values with more than 16 bits as
values for C shorts. However, DLLCC does not seem to check for out of
bounds values, but silently casts the values to shorts. Here is an example:

        | pointer |
        pointer := External.CIntegerType short gcCalloc.
        pointer at: 0 put: 1000000.
        pointer at: 0 "-> 16960"

The same code with a LargeInteger leads to an "improper store error".

CPointer>>contents: calls primitive 483, at:put: uses primitive 491. The
truncation seems to happen there. The comment of the method for
primitive 491 says "Fail if ... any of the arguments are invalid." Out
of bounds values are apparently not considered invalid.

When a CDatum responds to #contents:, it delegates to its type. A
CIntegerType then does type checking before setting the contents.
However, in CIntegerType>>coerceForAssignment:, it only checks if the
argument is an Integer. This leads to an "improperStoreError" instead of
an IllegalAssignmentSignal in the following code:

        | datum |
        datum := CIntegerType short newInFixedSpace.
        datum contents: 1000000.

It would be easy to check if the Integer is out of bounds in
coerceForAssignment:, as CIntegerType implements two methods maxVal and
minVal.

Would you consider the implicit type casts a bug or a feature?

While it's good to know that DLLCC will not produce a buffer overflow
when handed Integers which are too large for a C variable, it's
difficult to find errors when the out-of-range checks don't raise an
Exception. I would consider it a bug when an application tries to store
large Integers into shorts, which are then silently truncated. It may
lead to wrong results in the C code. Example:

        | jvm class |
        jvm := JVM current.
        class := jvm findClass: #'java.lang.Short'.
        class new_short: 1000000. "-> 16960"

It might be better to raise an Exception in that case. This could be a
Notification which does not automatically open a debugger, it does not
necessarily have to be an Error.

Best regards,
Joachim Geidel