[Seaside] WAUrl class>>#decodePercent:

jtuchel at objektfabrik.de jtuchel at objektfabrik.de
Thu Aug 29 05:46:07 UTC 2013


Hi Philippe,

please find the stacktrace attached. As I mentioned, I am on VA ST, so 
don't be surprised if the trace looks a bit different.

What is happening is that Seaside receives an Ajax request with one of 
its parameters containing the String 'test%'.
The String has not been URI encoded or anything in the Javascript code, 
it was just retrieved from a text input field using its .val() method.
Removing $% from the string before sending an Ajax request solves the 
problem.
encodeURI() would solve it as well, but that brings up a new problem, 
because the String received at the server side then is encoded and has 
to be decoded before it can be processed. AFAIK, VAST cannot do that yet 
- which is another story...

You may argue that it is never a good idea to not encode Ajax 
parameters, and I have a hard time finding counter arguments. But I 
think the way the error shows up in the end (reading beyond the end of 
the input stream) is misleading.
So as Johan already said, maybe the only way to improve things here is 
to throw a better exception.

I hope I could clarify the point with this message. Please feel free to 
ask if you need more information

Joachim

Am 27.08.13 18:34, schrieb Philippe Marschall:
> On Thu, Aug 22, 2013 at 7:26 AM, jtuchel at objektfabrik.de
> <jtuchel at objektfabrik.de> wrote:
>> Hi,
>>
>> I just stumbled across a problem when processing an Ajax callback for a
>> specialized autocompleter. I get a server side "Index out of range" if I
>> enter a String ending with $% into the textInput (which I have to supress
>> anyways, but that is another story).
>>
>> The problem is in WAUrl class>>#decodePercent: . the method doesn't check if
>> the percent character is the last in the url string.
>>
>> You can recreate the problem by evaluating
>>
>> WAUrl decodePercent: 'abc%'
>>
>> Please note that in Pharo 2.0 I get another exception (receiver of
>> asUpppercase is nil), but still this doesn't work. So I guess my code ( I am
>> using VA Smalltalk and its older version of Seaside) would also fail on the
>> current stable Seaside version.
> Sorry I somehow missed this thread. Who is sending #decodePercent: to
> WAUrl message? Can you provide a stack trace?
>
> Cheers
> Philippe
> _______________________________________________
> seaside mailing list
> seaside at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>


-- 
-- 
----------------------------------------------------------------------- 
Objektfabrik Joachim Tuchel          mailto:jtuchel at objektfabrik.de 
Fliederweg 1                         http://www.objektfabrik.de
D-71640 Ludwigsburg 		     http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1

-------------- next part --------------
Debugger Stack Trace Report:
Error String: '(ExCLDTIndexOutOfRange) Index out of range.'
Resumable: false

Process
	Name: Dispatch worker: 195525
	Process State: suspended
	Priority: 3

Executing in: WAUrl>>#parseQuery:

System Configuration Dump


Copyright:

	VA Smalltalk V8.5.2; Image: 8.5.2 [232]
	VM Timestamp: 4.0,(NC) 8/7/2012 (84)
	(C) Copyright Instantiations 1994, 2012.  All rights reserved.
	(C) Copyright International Business Machines Corp. 1994, 2006.  All rights reserved.

Time:  07:33:35
Date:  29.08.2013

Platform:

	Virtual machine:  ES
	Bytecode version:  4.0
	Manager version:  4.00
	'OS' subsystem:  'WIN32s'
	'CLIM' subsystem:  'ES'
	'CP' subsystem:  'WIN32s'
	'CLDT' subsystem:  'ES'
	'CFS' subsystem:  'WIN32s'
	'SCI' subsystem:  'WIN'
	'CW' subsystem:  'WIN32s'
	'CPM' subsystem:  'ES'
	'CG' subsystem:  'WIN32s'
	'CPIC' subsystem:  'WIN32s'

Current user:  Joachim Tuchel

Connected Library:

	Pathname: 
	Library version:  6
	Size of library:  266785184 bytes
	Has consistent EOF:  true
	Acquire read locks:  false
	Single user mode:  false
	Server address:  '192.168.xx.xx'

Library Access:

	Host system name:  None
	Use release lock mode:  true
	Native primitives library:  
	Emsrv primitives library:  

Memory:

	Total allocation:  78278020 bytes
	Available:  1063868 bytes
	Fixed Space:  35360 bytes
	New Space:  144784 bytes
	Old Space:  918472 bytes

=============<STACK TRACE BEGINS>============
[] in <optimized block>(ExceptionalEvent class)>>#initializeSystemExceptions
	signal=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
Signal>>#evaluate:
	self=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
	aBlock=[] in ExceptionalEvent class>>#initializeSystemExceptions
Signal>>#evaluateDefaultHandler:
	self=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
	aBlock=[] in ExceptionalEvent class>>#initializeSystemExceptions
ExceptionalEvent>>#applyDefaultHandler:
	self=Exception: (ExCLDTIndexOutOfRange) Index out of range.
	aSignal=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
	exception=Exception: (ExCLDTIndexOutOfRange) Index out of range.
Signal>>#handlesByDefault
	self=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
[] in BlockContextTemplate(Block)>>#when:do:exitWith:retryReturn:
	self=[] in SstHttpInvokerServlet>>#service:
	exception=Exception: (ExSstHttpRequestError) A servlet request error has occurred.
	handlerBlock=[] in SstHttpInvokerServlet>>#service:
	exitBlock=[] in Block>>#when:do:
	knownResult=an Object
	retryBlock=[] in Block>>#when:do:exitWith:retryReturn:
	handler=[] in Block>>#when:do:exitWith:retryReturn:
	oldHandler=nil
	signal=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
ExceptionalEvent>>#signalFor:
	self=Exception: (ExCLDTIndexOutOfRange) Index out of range.
	aSignalOrExceptionSelector=Signal on Exception: (ExCLDTIndexOutOfRange) Index out of range.
	handler=[] in Block>>#when:do:exitWith:retryReturn:
ExceptionalEvent>>#signalWithArguments:
	self=Exception: (ExCLDTIndexOutOfRange) Index out of range.
	arguments=()
ExceptionalEvent>>#signal
	self=Exception: (ExCLDTIndexOutOfRange) Index out of range.
ReadStream>>#next
	self=a ReadStream
WAUrl class>>#decodePercent:
	self=WAUrl
	aString='test%'
	input=a ReadStream
	output=a WriteStream
	char=$%
	value -> 37 (16r25)
	isLowercase -> false
	isUppercase -> false
	isDigit -> false
	isLetter -> false
	isPunctuation -> true
	isSeparator -> false
WAUrl>>#decode:
	self=/?_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-
	aString='test%'
WAUrl>>#parseQuery:
	self=/?_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-
	aString='_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-&19=test%'
	input=a ReadStream
	string='19=test%'
	index=3
WAUrl>>#initializeFromString:
	self=/?_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-
	aString='/kontolino?_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-&19=test%'
	string='/kontolino?_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-&19=test%'
	index=13
WAUrl class>>#absolute:
	self=WAUrl
	aString='/kontolino?_s=t0JuC1crW9NO2Bw5&_k=8qoE8Ph8YOUaO2a-&19=test%'
WASstServerAdaptor(WASstRequestConverter)>>#requestUrlFor:
	self=a WASstServerAdaptor
	aNativeRequest=a SstHttpServletRequest
WASstServerAdaptor(WAServerAdaptor)>>#requestFor:
	self=a WASstServerAdaptor
	aNativeRequest=a SstHttpServletRequest
WASstServerAdaptor(WAServerAdaptor)>>#contextFor:
	self=a WASstServerAdaptor
	aNativeRequest=a SstHttpServletRequest
WASstServerAdaptor(WAServerAdaptor)>>#process:
	self=a WASstServerAdaptor
	aNativeRequest=a SstHttpServletRequest
	context=nil
[] in WASstServerAdaptor>>#process:
	self=a WASstServerAdaptor
	aNativeRequest=a SstHttpServletRequest
	response=nil
WASstServerAdaptor>>#process:
	self=a WASstServerAdaptor
	aNativeRequest=a SstHttpServletRequest
	response=nil
WASstHttpServlet>>#doGet:
	self=a WASstHttpServlet
	message=a SstHttpServletRequest
	response=nil
[] in WASstHttpServlet(SstHttpServlet)>>#service:
	self=a WASstHttpServlet
	message=a SstHttpServletRequest
	selector=#doGet:
LookupTable>>#at:ifPresent:
	self=LookupTable(#doOptions: #doHead: #doDelete: #doGet: #doPost: #doPut: #doTrace: )
	aKey='GET'
	aBlock=[] in SstHttpServlet>>#service:
	hashIndex=14
	element='GET'
	elementsSize=22
	index=14
WASstHttpServlet(SstHttpServlet)>>#service:
	self=a WASstHttpServlet
	message=a SstHttpServletRequest
SstHttpInvokerServlet>>#basicService:
	self=a SstHttpInvokerServlet
	request=a SstHttpServletRequest
	servlet=a WASstHttpServlet
[] in SstHttpInvokerServlet>>#service:
	self=a SstHttpInvokerServlet
	request=a SstHttpServletRequest
BlockContextTemplate(Block)>>#valueWithErrorHandler:oldHandler:onReturnDo:
	self=[] in SstHttpInvokerServlet>>#service:
	handler=[] in Block>>#when:do:exitWith:retryReturn:
	oldHandler=nil
	completionBlock=[]
BlockContextTemplate(Block)>>#when:do:exitWith:retryReturn:
	self=[] in SstHttpInvokerServlet>>#service:
	exception=Exception: (ExSstHttpRequestError) A servlet request error has occurred.
	handlerBlock=[] in SstHttpInvokerServlet>>#service:
	exitBlock=[] in Block>>#when:do:
	knownResult=an Object
	retryBlock=[] in Block>>#when:do:exitWith:retryReturn:
	handler=[] in Block>>#when:do:exitWith:retryReturn:
	oldHandler=nil
BlockContextTemplate(Block)>>#when:do:
	self=[] in SstHttpInvokerServlet>>#service:
	exception=Exception: (ExSstHttpRequestError) A servlet request error has occurred.
	handlerBlock=[] in SstHttpInvokerServlet>>#service:
	knownResult=an Object
	result=nil
SstHttpInvokerServlet>>#service:
	self=a SstHttpInvokerServlet
	request=a SstHttpServletRequest
WASstHttpServletEngine(SstHttpServletEngine)>>#basicProcessRequest:
	self=a WASstHttpServletEngine
	servletRequest=a SstHttpServletRequest
	responseContent=nil
	responseMessage=false
WASstHttpServletEngine(SstBasicServer)>>#processClientRequest:
	self=a WASstHttpServletEngine
	request=a SstHttpServletRequest
	context=a SstServletContext
	sessionManager=a SstHttpSessionManager
	result=nil
WASstHttpServletEngine(SstHttpServer)>>#processClientRequest:
	self=a WASstHttpServletEngine
	request=a SstHttpServletRequest
	response=nil
WASstHttpServletEngine(SstHttpServletEngine)>>#processClientRequest:
	self=a WASstHttpServletEngine
	request=a SstByteMessage
WASstHttpServletEngine(SstBasicServer)>>#processRequest:
	self=a WASstHttpServletEngine
	request=a SstByteMessage
SstRequest(DirectedMessage)>>#send
	self=SstRequest (a WASstHttpServletEngine, #processRequest:, (a SstByteMessage))
[] in SstPooledDispatcher(SstDispatcher)>>#basicExecuteRequest:
	self=a SstPooledDispatcher
	request=SstRequest (a WASstHttpServletEngine, #processRequest:, (a SstByteMessage))
	sstTag=#SstTag:Execute
	savedRequest=nil
	oldErrorHandler=nil
SstPooledDispatcher(SstDispatcher)>>#basicExecuteRequest:
	self=a SstPooledDispatcher
	request=SstRequest (a WASstHttpServletEngine, #processRequest:, (a SstByteMessage))
	sstTag=#SstTag:Execute
	savedRequest=nil
	oldErrorHandler=nil
SstPooledDispatcher(SstDispatcher)>>#dispatchRequest:
	self=a SstPooledDispatcher
	request=SstRequest (a WASstHttpServletEngine, #processRequest:, (a SstByteMessage))
	result=SstInvocationHandler(http://:8080/)
[] in SstPooledDispatcher>>#dispatchRequest:
	self=a SstPooledDispatcher
	request=SstRequest (a WASstHttpServletEngine, #processRequest:, (a SstByteMessage))
[] in SstWorkerManager>>#blockFor:forWorker:
	self=a SstWorkerManager
	workBlock=[] in SstPooledDispatcher>>#dispatchRequest:
	worker=SstWorker(Dispatch worker: 195525; occupied)
[] in SstWorker>>#workBlock
	self=SstWorker(Dispatch worker: 195525; occupied)
	current=[] in SstWorkerManager>>#blockFor:forWorker:
[] in Process>>#executeBlock:withArguments:
	self=Process:Dispatch worker: 195525{suspended,3}
	aBlock=[] in SstWorker>>#workBlock
	args=()
Process>>#executeBlock:withArguments:
	self=Process:Dispatch worker: 195525{suspended,3}
	aBlock=[] in SstWorker>>#workBlock
	args=()
Process>>#newProcessOn:stackSize:withArguments:named:
	self=Process:Dispatch worker: 195525{suspended,3}
	aBlock=[] in SstWorker>>#workBlock
	stackSize=1024
	args=()
	procName='195525'
==============<STACK TRACE ENDS>=============


More information about the seaside mailing list