[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