You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2023/08/22 08:19:42 UTC

[httpcomponents-core] branch master updated: Filter characters before byte conversion (#416)

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 4e72f40df Filter characters before byte conversion (#416)
4e72f40df is described below

commit 4e72f40df8b03247afcddd19b2c64b8a432c2632
Author: vismayku <14...@users.noreply.github.com>
AuthorDate: Tue Aug 22 04:19:36 2023 -0400

    Filter characters before byte conversion (#416)
---
 .../http/impl/nio/SessionOutputBufferImpl.java     |  8 +++++--
 .../org/apache/hc/core5/util/ByteArrayBuffer.java  | 10 +++-----
 .../java/org/apache/hc/core5/util/TextUtils.java   | 17 +++++++++++++
 .../http/impl/nio/TestSessionInOutBuffers.java     | 28 ++++++++++++++++++++++
 4 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java
index 77cd9951f..922d025dc 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/SessionOutputBufferImpl.java
@@ -42,6 +42,8 @@ import org.apache.hc.core5.http.nio.SessionOutputBuffer;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.CharArrayBuffer;
 
+import static org.apache.hc.core5.util.TextUtils.filterIfRequired;
+
 class SessionOutputBufferImpl extends ExpandableBuffer implements SessionOutputBuffer {
 
     private static final byte[] CRLF = new byte[] {Chars.CR, Chars.LF};
@@ -171,12 +173,14 @@ class SessionOutputBufferImpl extends ExpandableBuffer implements SessionOutputB
                     final int off = buffer().position();
                     final int arrayOffset = buffer().arrayOffset();
                     for (int i = 0; i < len; i++) {
-                        b[arrayOffset + off + i]  = (byte) lineBuffer.charAt(i);
+                        final int c = lineBuffer.charAt(i);
+                        b[arrayOffset + off + i] = filterIfRequired(c);
                     }
                     buffer().position(off + len);
                 } else {
                     for (int i = 0; i < lineBuffer.length(); i++) {
-                        buffer().put((byte) lineBuffer.charAt(i));
+                        final int c = lineBuffer.charAt(i);
+                        buffer().put(filterIfRequired(c));
                     }
                 }
             } else {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java b/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java
index c9479c320..f6faeaf78 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/util/ByteArrayBuffer.java
@@ -30,6 +30,8 @@ package org.apache.hc.core5.util;
 import java.io.Serializable;
 import java.nio.ByteBuffer;
 
+import static org.apache.hc.core5.util.TextUtils.filterIfRequired;
+
 /**
  * A resizable byte array.
  *
@@ -139,13 +141,7 @@ public final class ByteArrayBuffer implements Serializable {
 
         for (int i1 = off, i2 = oldlen; i2 < newlen; i1++, i2++) {
             final int c = b[i1];
-            if ((c >= 0x20 && c <= 0x7E) || // Visible ASCII
-                (c >= 0xA0 && c <= 0xFF) || // Visible ISO-8859-1
-                c == 0x09) {                // TAB
-                this.array[i2] = (byte) c;
-            } else {
-                this.array[i2] = '?';
-            }
+            this.array[i2] = filterIfRequired(c);
         }
         this.len = newlen;
     }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/util/TextUtils.java b/httpcore5/src/main/java/org/apache/hc/core5/util/TextUtils.java
index a8b6a6e28..74c44cdae 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/util/TextUtils.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/util/TextUtils.java
@@ -26,6 +26,7 @@
  */
 
 package org.apache.hc.core5.util;
+import org.apache.hc.core5.annotation.Internal;
 
 import java.util.Locale;
 
@@ -141,4 +142,20 @@ public final class TextUtils {
         return s.toLowerCase(Locale.ROOT);
     }
 
+    /**
+     * Filter characters before byte conversion
+     *
+     * @since 5.2
+     */
+    @Internal
+    public static byte filterIfRequired(final int c) {
+        if ((c >= 0x20 && c <= 0x7E) || // Visible ASCII
+            (c >= 0xA0 && c <= 0xFF) || // Visible ISO-8859-1
+             c == 0x09) {               // TAB
+            return (byte) c;
+        } else {
+            return '?';
+        }
+    }
+
 }
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestSessionInOutBuffers.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestSessionInOutBuffers.java
index 7579a1fc5..0f4d1bba8 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestSessionInOutBuffers.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestSessionInOutBuffers.java
@@ -194,6 +194,34 @@ public class TestSessionInOutBuffers {
         Assertions.assertEquals("One\r\nTwo\r\nThree\r\nFour\r\n", s);
     }
 
+    @Test
+    public void testNonASCIIWriteLine() throws Exception {
+        final String testString = "123\u010Anew-header-from-some-header:injected-value";
+        final String expectedResult = "123?new-header-from-some-header:injected-value";
+
+        final CharArrayBuffer chbuffer = new CharArrayBuffer(32);
+        final SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16);
+
+        chbuffer.clear();
+        chbuffer.append(testString);
+        outbuf.writeLine(chbuffer);
+
+        //this write operation should have no effect
+        outbuf.writeLine(null);
+
+        final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        final WritableByteChannel outChannel = newChannel(outStream);
+        outbuf.flush(outChannel);
+
+        final ReadableByteChannel channel = newChannel(outStream.toByteArray());
+
+        final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 16, 0);
+        inbuf.fill(channel);
+        chbuffer.clear();
+        inbuf.readLine(chbuffer, true);
+        Assertions.assertEquals(expectedResult, chbuffer.toString());
+    }
+
     @Test
     public void testBasicReadWriteLine() throws Exception {