This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: [PATCH] java.util.StringTokenizer assumes order of parameterevaluation
Hi,
On Wed, 2002-10-16 at 15:09, Andrew Haley wrote:
> Ranjit Mathew writes:
> > Sorry guys, but I just referred to the JLS (section 15.12.4.2,
> > "Evaluate Arguments"):
> >
> > http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#45449
> >
> > and I quote:
> >
> > "The argument expressions are evaluated in order, from left to right..."
> >
> > Therefore, the coder for StringTokenizer *can* assume the
> > order of evaluation - there must be some other problem that
> > I need to figure out.
> >
> > BTW, does GCJ guarantee this order at all times? (I just saw
> > Andrew Haley's patch for a fix for *static* method invocation,
> > but the StringTokenizer problem is in a member method.)
>
> Ah, here's another version of that patch. I won't commit it because
> it's not fully tested yet.
> [...]
> 2002-10-15 Andrew Haley <aph@redhat.com>
>
> * parse.y (patch_invoke): Call force_evaluation_order on a static
> arg list.
> (resolve_qualified_expression_name): Call force_evaluation_order
> on a arg list that is part of a Qualified Expression Name.
>
> * lang.c (dump_compound_expr): New.
> (java_dump_tree): New.
I saw that you applied this patch so I tried a new gcj checkout on the
attached testcase from Casey Marshall that he found when trying to
analyse why compiling GNU Crypto with gcj -O2 produced incorrect
results.
GNU Crypto already contains a workaround for this issue but the attached
program does not produce correct results (with or without! -O2).
It seems that the arguments to the methods get mixed up in the following
statement:
result[j++] = (byte)(
(fromDigit(s.charAt(i++)) << 4) | fromDigit(s.charAt(i++)));
Compiling with gcj -C produces bytecode that runs correctly with gij.
Correct output should be:
0123456789ABCDEF
0123456789ABCDEF
0123456789ABCDEF
But is:
0123456789ABCDEF
0123456789ABCDEF
1032547698BADCFE
Cheers,
Mark
class utilTest {
public static void main(String[] argv) throws Throwable {
byte[] b = new byte[] {
0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab,
(byte) 0xcd, (byte) 0xef
};
String s = "0123456789ABCDEF";
System.err.println(toString(b));
System.err.println(s);
System.err.println(toString(toBytesFromString(s)));
}
// The following comes from the GNU Crypto project gnu.crypto.util.Util
private static final char[] HEX_DIGITS = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
public static byte[] toBytesFromString(String s) {
int limit = s.length();
byte[] result = new byte[((limit + 1) / 2)];
int i = 0, j = 0;
if ((limit % 2) == 1) {
result[j++] = (byte) fromDigit(s.charAt(i++));
}
while (i < limit) {
result[j++] = (byte)(
(fromDigit(s.charAt(i++)) << 4) | fromDigit(s.charAt(i++)));
}
return result;
}
public static int fromDigit(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
} else
throw new IllegalArgumentException("Invalid hexadecimal digit: " + c);
}
public static String toString(byte[] ba) {
return toString(ba, 0, ba.length);
}
public static final String toString(byte[] ba, int offset, int length) {
char[] buf = new char[length * 2];
for (int i = 0, j = 0, k; i < length; ) {
k = ba[offset + i++];
buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
buf[j++] = HEX_DIGITS[ k & 0x0F];
}
return new String(buf);
}
}