[jcifs] SmbComWriteAndX writes corrupt offset to wire
Richard Heap
richardheap at beeb.net
Thu Apr 15 10:38:24 GMT 2004
SUCCESS!
(It turns out I was fooling myself that if I compiled the code it worked
- got my build of undoctored 8.2 to fail)
I made the changes that I suggested below (including writeLong) on 8.2,
rebuilt, and now it is running sweet as a nut.
Having found Barry's earlier posts (google must have been having an off
day when i was looking for similar problems before) I notice that he was
also using 1.4.2 (had to revert to 1.4.0 to get things to work), and
running Tomcat. I wonder if Barry was using -server? (I'd have been to
run tomcat...)
So...
it would appear that this is a JIT compiler bug in the server edition of
(at least) the linux J2SE JVM from Sun - version 1.4.2 (and 1.5), that....
can be alleviated by making the jcifs code a little simpler (and maybe
even faster ;-))
Thanks Again
Richard
Richard Heap wrote:
> Firstly, if you are still interested, let's attempt to get you to
> where you can reproduce it. Attached is my test harness (compiled on
> Windows, incidentally).
> Test environment is Redhat linux 9 kernel 2.4.20 single cpu 1GHz PIII
> - i.e. kernel has native posix threads
> Sun J2SE 1.4.2_01, or _04 or 1.5Beta1
> command line is:
> /path/to/java -server -cp testjcifs.jar:jcifs-0.8.2.jar
> testjcifs.FullTest <shareurl> <auth info> [<sleep factor - default 1000]>
> e.g.
> /path/to/java -server -cp testjcifs.jar:jcifs-0.8.2.jar
> testjcifs.FullTest smb://192.168.30.30/testshare/ Richard 500
> this creates a handful of threads
> one writes
> one deletes (after a while)
> one creates readers, that...
> read(!)
> The readers spot the corruption, and complain to standard out
> Normally breaks in less than a minute
>
> Then... I wonder if you would do me the favour of compiling, say, 8.2,
> with the following changes (remember that if I compile any version of
> the library we seem *not* to get the problem)
> SmbComWriteAndX.writeParameterWordsWireFormat is slightly simplified to...
> int writeParameterWordsWireFormat( byte[] dst, int dstIndex ) {
> int start = dstIndex;
>
> dataOffset = dstIndex + 26; // 26 = off from here to pad
> /*
> * pad = ( dataOffset - headerStart ) % 4;
> * pad = pad == 0 ? 0 : 4 - pad;
> * dataOffset += pad;
> */
>
> writeInt2( fid, dst, dstIndex );
> dstIndex += 2;
> writeInt4( offset, dst, dstIndex );
> dstIndex += 4;
> for( int i = 0; i < 4; i++ ) {
> dst[dstIndex++] = (byte)0x00;
> }
> writeInt2( writeMode, dst, dstIndex );
> dstIndex += 2;
> writeInt2( remaining, dst, dstIndex );
> dstIndex += 2;
> dst[dstIndex++] = (byte)0x00;
> dst[dstIndex++] = (byte)0x00;
> writeInt2( dataLength, dst, dstIndex );
> dstIndex += 2;
> writeInt2( dataOffset, dst, dstIndex );
> dstIndex += 2;
> writeInt4( offset >> 32, dst, dstIndex );
> dstIndex += 4;
>
> return dstIndex - start;
> }
>
> and ServerMessageBlock is slightly simplified thus:
> static void writeInt2( long val, byte[] dst, int dstIndex ) {
> dst[dstIndex++] = (byte)(val);
> dst[dstIndex++] = (byte)(val >> 8);
> }
> static void writeInt4( long val, byte[] dst, int dstIndex ) {
> dst[dstIndex++] = (byte)(val);
> dst[dstIndex++] = (byte)(val >> 8);
> dst[dstIndex++] = (byte)(val >> 16);
> dst[dstIndex++] = (byte)(val >> 32);
> }
> (writeLong could get similar treatment)
>
> if nothing else these should save a few CPU cycles :-)
>
> Many Thanks
> Richard
>
>
> Michael B Allen wrote:
>
>>First, it's time I confess that I failed to mention that Barry (cc'd)
>>encountered this problem quite a while ago. I didn't tell you yesterday
>>because I didn't want to pollute your investigation with our ideas. And I
>>must say you have done a very good job at identifying the issues. Perhaps
>>Barry can confirm that your observations apply to his situation as well?
>>You can see in the message linked below that the offset is discussed.
>>Converting that offset value to hex shows that it indeed has the lower
>>byte truncated.
>>
>>http://lists.samba.org/archive/jcifs/2003-October/002586.html
>>
>>
>>
>>>2004-04-14 12:53:54,441 ERROR [STDERR] queue.name.eqb:
>>>writeParameterWordsWireFormat: offset=4000
>>>2004-04-14 12:53:54,441 ERROR [STDERR]
>>>00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00 |ÿSMB/...........|
>>>00010: 00 00 00 00 00 00 00 00 02 30 0B 70 01 68 5F 0D |.........0.p.h_.|
>>>00020: 0E FF 00 00 00 0E C0>00<0F 00 00 00 00 00 00 00 |.ÿ....À.........|
>>>
>>>Note how the offset is corrupt even directly after
>>>writeParameterWordsWireFormat
>>>
>>>
>>
>>Well I'd say that narrows things down quite a bit. Here's the method in
>>question:
>>
>> int writeParameterWordsWireFormat( byte[] dst, int dstIndex ) {
>> int start = dstIndex;
>>
>> dataOffset = dstIndex + 26; // 26 = off from here to pad
>>
>> writeInt2( fid, dst, dstIndex );
>> dstIndex += 2;
>> writeInt4( offset & 0xFFFFFFFFL, dst, dstIndex );
>> dstIndex += 4;
>> for( int i = 0; i < 4; i++ ) {
>> dst[dstIndex++] = (byte)0x00;
>> }
>> writeInt2( writeMode, dst, dstIndex );
>> dstIndex += 2;
>> writeInt2( remaining, dst, dstIndex );
>> dstIndex += 2;
>> dst[dstIndex++] = (byte)0x00;
>> dst[dstIndex++] = (byte)0x00;
>> writeInt2( dataLength, dst, dstIndex );
>> dstIndex += 2;
>> writeInt2( dataOffset, dst, dstIndex );
>> dstIndex += 2;
>> writeInt4(( offset >> 32 ) & 0xFFFFFFFFL, dst, dstIndex );
>> dstIndex += 4;
>>
>> return dstIndex - start;
>> }
>>
>>Note the offset variable is a member of SmbComWriteAndX that is set with
>>setParam in SmbFileOutputStream.write but none of that data is static and
>>even if a user incorrectly called it concurrently I don't see how it could
>>account for the bazaar behavior we're seeing. So it has to be something
>>in this method. What is it about the offset variable that causes *it* to
>>be encoded incorrectly. Perhaps it's the inlined & 0xFFFFFFFFL or >> ...
>>etc?
>>
>>
>>
>>>The interesting thing is that I have found the 'trigger' that causes it
>>>to 'break'. The previous file copied is longer than normal, and, in
>>>fact, the offset breaks half way through the file, as follows....
>>>
>>>writeParameterWordsWireFormat: offset=100000
>>>2004-04-14 12:53:54,244 ERROR [STDERR]
>>>00000: FF 53 4D 42 2F 00 00 00 00 18 03 80 00 00 00 00 |ÿSMB/...........|
>>>00010: 00 00 00 00 00 00 00 00 02 30 0B 70 01 68 0D 0D |.........0.p.h..|
>>>00020: 0E FF 00 00 00 0D C0>00<86 01 00 00 00 00 00 00 |.ÿ....À.........|
>>>
>>>Notice how 92000 is encoded ok, 100000 is encoded incorrectly.
>>>This longer than normal file seems to be the trigger that permanently
>>>breaks the encoding.
>>>
>>>
>><snip>
>>
>>
>>>So back to the test harness - now modified to throw in a few files >
>>>100000 bytes. It won't break on Windows at all, and it won't break with
>>>the client JVM on linux. It only breaks with the -server option. I've
>>>tried 1.4.2_01 and 1.4.2_04 - same result. I'm downloading 1.5 at the
>>>moment to see if that changes anything. (And just about to test the real
>>>application without -server). Will let you know.
>>>
>>>
>>
>>Mmm, I modified my test program to write a larger file every 50 loops
>>with 1.3.1_08-b03 and the -server option compiled on Linux for over
>>an hour and still I cannot reproduce this :(
>>
>>[in a followup message ...]
>>
>>
>>
>>>J2SE 1.5 didn't make any difference, but what did was compiling the
>>>library myself (using 1.4.2 under windows) - can now run the test
>>>harness with -server on linux without problem. Also confirmed that the
>>>real application seems to work ok (so far) without -server.
>>>
>>>So looks like I have a couple of choices... don't use -server on linux -
>>>or - compile the library myself
>>>
>>>
>>
>>So -server is required as is compiling on Linux? Did you recompile jCIFS,
>>your app, or both? I guess this suggests the javac compiler on Linux is
>>doing something the HotSpot VM doesn't like?
>>
>>For some reason I cannot get into the java.sun.com bug tracking system
>>but I sent Java Developer Support a note. Maybe they have some input.
>>
>>Mike
>>
>>
>>
>>
-------------- next part --------------
HTML attachment scrubbed and removed
More information about the jcifs
mailing list