tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 19545] New: - CGIServlet accidentaly changes content-length
Date Fri, 02 May 2003 08:50:56 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=19545>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=19545

CGIServlet accidentaly changes content-length

           Summary: CGIServlet accidentaly changes content-length
           Product: Tomcat 4
           Version: 4.1.24
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: Servlets:CGI
        AssignedTo: tomcat-dev@jakarta.apache.org
        ReportedBy: artonx@yahoo.co.jp


There are 3 problems on CGIServlet.
1st: need CONTENT_LENGTH variable justification
 the situation: The client's input multibyte character may or may not be 
encoded as a pair of bytes. for example the shift_jis code 0x83-0x65 was 
encoded into "%83e" by the user-agent(this was produced by IE6). But re-encoded 
data from Catalina to CGIServlet was encoded into "%83%65". I think it's not a 
problem but behaviour.
The problme is, after changing entire size of the content (because "%83e" - 
length=4, but "%83%65" - length = 6), the "CONTENT_LENGTH" variable isn't 
adjusted. So the CGI program can't read entire message body, because the 
program read within CONTENT_LENGTH bytes as the matter of CGI specification.
say "it must not attempt to read more than CONTENT_LENGTH bytes" by http://cgi-
spec.golux.com/cgi-120-00a.html#7.0.
2nd: It's too late to adjust CONTETN_LENGTH
 CGIServlet modifies CONTETN_LENGTH after the CGI program was executed. I faced 
the problem that the CGI program start to read CONTENT_LENGTH bytes before 
CGIServlet set modified CONTETN_LENGTH. -- This modification by CGIServlet is 
from CGIRunner#getPostInput.
3rd: CGIRunner#getPostInput put the content twice.
 I think it's bad behaviour because the CGI program read the data twice, and I 
didn't figure out why the CGIServlet does this.

Here is patch:
diff -u CGIServlet.java.org CGIServlet.java
--- CGIServlet.java.org	Fri May 02 02:57:25 2003
+++ CGIServlet.java	Fri May 02 17:14:05 2003
@@ -73,6 +73,7 @@
 import java.io.OutputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.IOException;
@@ -1584,9 +1585,44 @@
             cmdAndArgs = perlCommand;
         }
 
+      String sContentLength = (String) env.get("CONTENT_LENGTH");
+      ByteArrayOutputStream contentStream = null;
+      if(!"".equals(sContentLength)) {
+          byte[] content = new byte[Integer.parseInt(sContentLength)];
+          int lenRead = stdin.read(content);
+	  contentStream = new ByteArrayOutputStream(Integer.parseInt
(sContentLength));
+          if ("POST".equals(env.get("REQUEST_METHOD"))) {
+              String paramStr = getPostInput(params);
+              if (paramStr != null) {
+                  byte[] paramBytes = paramStr.getBytes();
+		  contentStream.write(paramBytes);
+
+		  int contentLength = paramBytes.length;
+                  if (lenRead > 0) {
+                      String lineSep = System.getProperty("line.separator");
+                      contentStream.write(lineSep.getBytes());
+                      contentLength = lineSep.length() + lenRead;
+                  }
+                  env.put("CONTENT_LENGTH", new Integer(contentLength));
+              }
+          }
+
+          if (lenRead > 0) {
+	      contentStream.write(content, 0, lenRead);
+          }
+	  contentStream.close();
+      }
+
             rt = Runtime.getRuntime();
             proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd);
 
+
+      if(contentStream != null) {
+          commandsStdIn = new BufferedOutputStream(proc.getOutputStream());
+          proc.getOutputStream().write(contentStream.toByteArray());
+          commandsStdIn.flush();
+          commandsStdIn.close();
+      }
             /*
              * provide input to cgi
              * First  -- parameters
@@ -1649,40 +1685,6 @@
             }
             commandsStdIn.flush();
             commandsStdIn.close();*/
-      String sContentLength = (String) env.get("CONTENT_LENGTH");
-      if(!"".equals(sContentLength)) {
-          commandsStdIn = new BufferedOutputStream(proc.getOutputStream());
-          byte[] content = new byte[Integer.parseInt(sContentLength)];
-
-          int lenRead = stdin.read(content);
-
-          if ("POST".equals(env.get("REQUEST_METHOD"))) {
-              String paramStr = getPostInput(params);
-              if (paramStr != null) {
-                  byte[] paramBytes = paramStr.getBytes();
-                  commandsStdIn.write(paramBytes);
-
-                  int contentLength = paramBytes.length;
-                  if (lenRead > 0) {
-                      String lineSep = System.getProperty("line.separator");
-
-                      commandsStdIn.write(lineSep.getBytes());
-
-                      contentLength = lineSep.length() + lenRead;
-                  }
-
-                  env.put("CONTENT_LENGTH", new Integer(contentLength));
-              }
-          }
-
-          if (lenRead > 0) {
-              commandsStdIn.write(content, 0, lenRead);
-          }
-
-
-          commandsStdIn.flush();
-          commandsStdIn.close();
-      }
 
             /* we want to wait for the process to exit,  Process.waitFor()
              * is useless in our situation; see
@@ -1803,26 +1805,23 @@
         protected String getPostInput(Hashtable params) {
             String lineSeparator = System.getProperty("line.separator");
             Enumeration paramNames = params.keys();
-            StringBuffer postInput = new StringBuffer("");
             StringBuffer qs = new StringBuffer("");
             if (paramNames != null && paramNames.hasMoreElements()) {
                 while (paramNames.hasMoreElements()) {
                     String k = (String) paramNames.nextElement();
                     String v = params.get(k).toString();
                     if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {
-                        postInput.append(k);
                         qs.append(k);
-                        postInput.append("=");
                         qs.append("=");
-                        postInput.append(v);
                         qs.append(v);
-                        postInput.append(lineSeparator);
                         qs.append("&");
                     }
                 }
             }
-            qs.append(lineSeparator);
-            return qs.append(postInput.toString()).toString();
+	    if (qs.charAt(qs.length() - 1) == '&') {
+		qs.setLength(qs.length() - 1);
+	    }
+            return qs.toString();
         }

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org


Mime
View raw message