[GB.XML.RPC]

* BUG: miniServer would give an out-of-bound with multiple parallel requests


git-svn-id: svn://localhost/gambas/trunk@5971 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Alexander Kuiper 2013-11-23 19:41:35 +00:00
parent f3264a5126
commit 183bfa39d7

View file

@ -28,16 +28,10 @@
'
'***************************************************************************
Private Http As ServerSocket
Private hSocket As Object[]
Private hBuffer As String[]
Private hProt As Short[]
Private hLen As Integer[]
Private hConn As Integer[]
Private hType As Byte[]
Private SockColl As Collection
Private hReply As String
Event GotData(Data As String)
Event ProcessData(Data As String)
@ -73,18 +67,12 @@ End
Private Sub RemoveSocket(hS As Socket)
Dim Bucle As Integer
Dim cCol As Collection
For Bucle = 0 To hSocket.Count - 1
If hS = hSocket[Bucle] Then
For Each cCol In SockColl
If hS = cCol["socket"] Then
Try Close #hS
hSocket.Remove(Bucle)
hBuffer.Remove(Bucle)
hLen.Remove(Bucle)
hProt.Remove(Bucle)
hConn.Remove(Bucle)
hType.Remove(Bucle)
SockColl.Remove(cCol["id"])
Break
End If
@ -231,22 +219,23 @@ Public Sub Socket_Read()
Dim cCount As Integer
Dim cLen As Integer
Dim cWait As Integer = 1
Dim cCol As Collection
For Bucle = 0 To hSocket.Count - 1
If hSocket[Bucle] = Last Then
For Each cCol In SockColl
If cCol["socket"] = Last Then
hS = Last
Break
End If
Endif
Next
If hS = Null Then Return
If hBuffer[Bucle] = "" Then
If cCol["buffer"] = "" Then
If Lof(hS) >= 5 Then
Try Read #hS, Buf, Lof(hS)
hBuffer[Bucle] = hBuffer[Bucle] & Buf
If Left(hBuffer[Bucle], 5) <> "POST " Then
cCol["buffer"] &= Buf
If Left(cCol["buffer"], 5) <> "POST " Then
hError(hS, "405 Method Not Allowed")
RemoveSocket(hS)
Return
@ -255,21 +244,21 @@ Public Sub Socket_Read()
End If
Else
Try Read #hS, Buf, Lof(hS)
hBuffer[Bucle] = hBuffer[Bucle] & Buf
cCol["buffer"] &= Buf
' Don't continue, because this is the second (or more) iteration to read the data
' The first iteration will handle the complete request
Return
End If
If hProt[Bucle] = - 1 Then
If InStr(hBuffer[Bucle], Chr(13)) > 0 Then
Buf = Trim(Left(hBuffer[Bucle], InStr(hBuffer[Bucle], Chr(13)) - 1))
If cCol["protocol"] = - 1 Then
If InStr(cCol["buffer"], Chr(13)) > 0 Then
Buf = Trim(Left(cCol["buffer"], InStr(cCol["buffer"], Chr(13)) - 1))
Buf = Right(Buf, 8)
If Buf = "HTTP/1.1" Then
hProt[Bucle] = 1
cCol["protocol"] = 1
Else If Buf = "HTTP/1.0" Then
hProt[Bucle] = 0
cCol["protocol"] = 0
Else
hError(hS, "505 HTTP Version Not Supported")
RemoveSocket(hS)
@ -277,7 +266,7 @@ Public Sub Socket_Read()
End If
Else
If Len(hBuffer[Bucle]) > 4096 Then
If Len(cCol["buffer"]) > 4096 Then
hError(hS, "413 Request Entity Too Large")
RemoveSocket(hS)
Return
@ -288,13 +277,13 @@ Public Sub Socket_Read()
' It is possible the HTTP headers are send in separate TCP packets, we will wait a maximum of 1000msec
For cCount = cWait To 199 Step 1
If hS = Null Then Return
If InStr(hBuffer[Bucle], Chr(13) & Chr(10) & Chr(13) & Chr(10)) Then Break
If InStr(cCol["buffer"], Chr(13) & Chr(10) & Chr(13) & Chr(10)) Then Break
Wait 0.005
Next
If InStr(hBuffer[Bucle], Chr(13) & Chr(10) & Chr(13) & Chr(10)) Then
If hType[Bucle] = 0 Then
Buf = Left(hBuffer[Bucle], InStr(hBuffer[Bucle], Chr(13) & Chr(10) & Chr(13) & Chr(10)))
If InStr(cCol["buffer"], Chr(13) & Chr(10) & Chr(13) & Chr(10)) Then
If cCol["type"] = 0 Then
Buf = Left(cCol["buffer"], InStr(cCol["buffer"], Chr(13) & Chr(10) & Chr(13) & Chr(10)))
If InStr(UCase(Buf), "CONTENT-TYPE:") > 0 Then
sCad = Mid(Buf, InStr(UCase(Buf), "CONTENT-TYPE:") + 13)
@ -304,7 +293,7 @@ Public Sub Socket_Read()
RemoveSocket(hS)
Return
Else
hType[Bucle] = 1
cCol["type"] = 1
End If
Else
hError(hS, "415 Unsupported Media Type")
@ -315,7 +304,7 @@ Public Sub Socket_Read()
If InStr(UCase(Buf), "CONTENT-LENGTH:") > 0 Then
sCad = Mid(Buf, InStr(UCase(Buf), "CONTENT-LENGTH:") + 15)
sCad = Trim(Left(sCad, InStr(sCad, Chr(13))))
Try hLen[Bucle] = CInt(sCad)
Try cCol["length"] = CInt(sCad)
If Error Then
hError(hS, "411 Length Required")
RemoveSocket(hS)
@ -328,9 +317,9 @@ Public Sub Socket_Read()
End If
' Check for "Expect: 100-continue" option & HTTP/1.1
If hProt[Bucle] = 1 And InStr(UCase(Buf), "EXPECT: 100-CONTINUE") > 0 Then
If cCol["protocol"] = 1 And InStr(UCase(Buf), "EXPECT: 100-CONTINUE") > 0 Then
' Do a special check if no body is received - only then reply
If InStr(hBuffer[Bucle], Chr(13) & Chr(10) & Chr(13) & Chr(10)) + 3 = Len(hBuffer[Bucle]) Then
If InStr(cCol["buffer"], Chr(13) & Chr(10) & Chr(13) & Chr(10)) + 3 = Len(cCol["buffer"]) Then
hS.Begin
hS.EndOfLine = gb.Windows
Print #hS, "HTTP/1.1 100 Continue"
@ -342,9 +331,9 @@ Public Sub Socket_Read()
End If
End If
If InStr(hBuffer[Bucle], Chr(13) & Chr(10) & Chr(13) & Chr(10)) Then
If InStr(cCol["buffer"], Chr(13) & Chr(10) & Chr(13) & Chr(10)) Then
If hLen[Bucle] = - 1 Or hType[Bucle] <> 1 Then
If cCol["length"] = - 1 Or cCol["type"] <> 1 Then
hError(hS, "406 Not Acceptable")
RemoveSocket(hS)
Return
@ -352,19 +341,19 @@ Public Sub Socket_Read()
For cCount = cWait To 200 Step 1
If hS = Null Then Return
cLen = Len(hBuffer[Bucle]) - InStr(hBuffer[Bucle], Chr(13) & Chr(10) & Chr(13) & Chr(10)) - 3
If cLen >= hLen[Bucle] Then Break
cLen = Len(cCol["buffer"]) - InStr(cCol["buffer"], Chr(13) & Chr(10) & Chr(13) & Chr(10)) - 3
If cLen >= cCol["length"] Then Break
Wait 0.005
Next
' HTTP/1.0 = looseless checking, some older clients generation wrong length
' HTTP/1.1 = strict checking
If (hProt[Bucle] = 1 And hLen[Bucle] = cLen) Or (hProt[Bucle] = 0 And hLen[Bucle] <= cLen) Then
ProcessQuery(hS, hBuffer[Bucle])
If (cCol["protocol"] = 1 And cCol["length"] = cLen) Or (cCol["protocol"] = 0 And cCol["length"] <= cLen) Then
ProcessQuery(hS, cCol["buffer"])
Return
Else
If Len(hBuffer[Bucle]) > 4096 Then
If Len(cCol["buffer"]) > 4096 Then
hError(hS, "413 Request Entity Too Large")
RemoveSocket(hS)
Return
@ -378,7 +367,7 @@ Public Sub Socket_Read()
End If
Else
If Len(hBuffer[Bucle]) > 4096 Then
If Len(cCol["buffer"]) > 4096 Then
hError(hS, "413 Request Entity Too Large")
RemoveSocket(hS)
Return
@ -395,20 +384,33 @@ End
Public Sub Http_Connection(RemoteHost As String)
hSocket.Add(Http.Accept())
hBuffer.Add("")
hProt.Add(- 1)
hLen.Add(- 1)
hConn.Add(0)
hType.Add(0)
Dim SockCollEntry As New Collection
Dim iId As Integer
Randomize
Do
iId = Int(Rnd(1, 32768))
Loop Until Not SockColl.Exist(iId)
SockCollEntry.Add("", "buffer")
SockCollEntry.Add(Http.Accept(), "socket")
SockCollEntry.Add(-1, "protocol")
SockCollEntry.Add(-1, "length")
SockCollEntry.Add(0, "type")
SockCollEntry.Add(CStr(iId), "id")
SockColl.Add(SockCollEntry, CStr(iId))
End
Public Sub Close()
Do While hSocket.Count > 0
RemoveSocket(hSocket[0])
Loop
Dim cCol As Collection
For Each cCol In SockColl
RemoveSocket(cCol["socket"])
Next
Try Http.Close()
Http = Null
@ -442,17 +444,14 @@ Public Sub Listen(Port As Integer, MaxConn As Integer)
End
Public Sub _New()
hSocket = New Object[]
hBuffer = New String[]
hProt = New Byte[]
hLen = New Integer[]
hConn = New Integer[]
hType = New Byte[]
SockColl = New Collection
End
Public Sub _Free()
Me.Close()