[Seaside] random maddening bug - "corrupted" file upload contents

Bob Arning arning315 at comcast.net
Wed Jan 10 16:39:06 UTC 2018


I don't have it completely nailed, but the corruption is happening in here:

ZnUtils class>>readUpToEnd: inputStream limit: limit
     | species bufferSize buffer totalRead outputStream answer ch |
     bufferSize := limit ifNil: [ self streamingBufferSize ] ifNotNil: [ 
self streamingBufferSize min: limit ].
     species := inputStream isBinary ifTrue: [ ByteArray ] ifFalse: [ 
String ].
     buffer := species new: bufferSize.
     totalRead := 0.
     outputStream := nil.
     [ inputStream atEnd ] whileFalse: [ | readCount |
         readCount := inputStream readInto: buffer startingAt: 1 count: 
bufferSize.
         totalRead = 0 ifTrue: [
             ch := buffer first.
*BOB note2: { 'readUpToEnd:'. species . readCount. bufferSize. buffer 
copy. inputStream } this records the fact that data put into the 
beginning of the buffer is correct*
         ].
         totalRead := totalRead + readCount.
         (limit notNil and: [ totalRead > limit ])
             ifTrue: [ ZnEntityTooLarge signal ].
         outputStream ifNil: [
             inputStream atEnd
                 ifTrue: [ ^ buffer copyFrom: 1 to: readCount ]
                 ifFalse: [ outputStream := (species new: bufferSize) 
writeStream ] ].
*BOB watchit: true. this enables noting when the outputStream needs to 
grow a new collection*
         outputStream next: readCount putAll: buffer startingAt: 1.
*BOB watchit: false. this just turns it off*
*totalRead = readCount ifTrue: [BOB note2: { 'outcontents'. outputStream 
contents first: 100. outputStream }]. this verifies that buffer made it 
to outputStream correctly in the first pass*
*ch = outputStream contents first ifFalse: [ self halt ]. this tests 
every pass to see that the output is still good. And eventually it is NOT*
         self signalProgress: totalRead total: limit ].
     answer := outputStream ifNil: [ species new ] ifNotNil: [ 
outputStream contents ].
*BOB note2: { 'answer'. answer first: 100. outputStream }. this records 
what we are answering and it can be wrong.*
     ^answer

So what happens?
- data is added to the outputStream normally
- the outputStream collection grows in an ordinary-looking fashion
- then the check that *ch = outputStream contents first* fails -- the 
first 4 bytes in the outputStream are now zero.
- why here?
--- we have just written data that pushed the outputStream to 18186240 bytes
--- that write caused a grow from 18184052 to 22732263 in the stream's 
collection
--- after that grow/write, the initial bytes are changed -- something to 
do with the grow??
--- another interesting but likely irrelevant fact is that the data 
written just before the error is the last full 16384 from the file. The 
next and final buffer to be written will only be 15845 bytes, but that 
hasn't happened yet. so??

I've been trying to recreate the error with a simple loop writing data, 
but no success so far.

On 1/10/18 4:42 AM, Cyrille Delaunay wrote:
> ZnDefaultServerDelegate >> formTest3: request
> >       | contents filename contentType page |
> >       contents := filename := contentType := ''.
> >       (request hasEntity and: [ request contentType matches: 
> ZnMimeType multiPartFormData ])
> >               ifTrue: [
> >                       (request entity partNamed: #file ifNone: [ nil ])
> >                               ifNotNil: [ :part |
> >                                       filename := part fileName.
> >                                       contents := part contents.
> >                                       contentType := part contentType.
> >                                       contentType isBinary ifTrue: [ 
> contents := contents hex ] ] ].
> >       page := ZnHtmlOutputStream streamContents: [ :html |
> >               html page: 'Form Test 3' do: [
> >                       html
> >                               tag: #form
> >                               attributes: #(action 'form-test-3' 
> 'accept-charset' 'utf-8'
> >          enctype 'multipart/form-data' method POST)
> >                               do: [
> >                                       html
> >                                               str: 'File'; space;
> >                                               tag: #input 
> attributes: #(type file name file); space;
> >                                               tag: #input 
> attributes: #(type submit) ];
> >                               tag: #p do: [ html str: 'filename = '; 
> str: filename ];
> >                               tag: #p do: [ html str: 'content-type 
> = '; str: contentType asString ];
> >                               tag: #p do: [ html str: 'contents = '; 
> str: (contents copyFrom: 1 to: 20) asString ] ] ].
> >       ^ ZnResponse ok: (ZnEntity html: page)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/seaside/attachments/20180110/00e66c88/attachment.html>


More information about the seaside mailing list