Skip to content

Commit 1b2d2fc

Browse files
committed
Merge pull request #52280 from challa
Closes gh-52280 * pr/52280: Polish 'Encode single-byte characters correctly in UrlEncoder' Encode single-byte characters correctly in UrlEncoder
2 parents a233876 + dc53a64 commit 1b2d2fc

3 files changed

Lines changed: 50 additions & 10 deletions

File tree

‎loader/spring-boot-loader/src/main/java/org/springframework/boot/loader/net/util/UrlEncoder.java‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,28 @@ private static String encode(char[] path, int fromIndex) {
6565
result[size++] = ch;
6666
continue;
6767
}
68-
if (ch > 0x07FF) {
69-
size = escape(result, 0xE0 | ((ch >> 12) & 0x0F), size);
70-
size = escape(result, 0x80 | ((ch >> 6) & 0x3F), size);
71-
size = escape(result, 0x80 | ((ch >> 0) & 0x3F), size);
72-
}
73-
else {
74-
size = escape(result, 0xC0 | ((ch >> 6) & 0x1F), size);
75-
size = escape(result, 0x80 | ((ch >> 0) & 0x3F), size);
76-
}
68+
size = encode(ch, result, size);
7769
}
7870
return new String(result, 0, size);
7971
}
8072

81-
private static int escape(char[] result, int ch, int size) {
73+
private static int encode(char ch, char[] result, int size) {
74+
if (ch <= 0x007F) {
75+
size = encodeByteChar(result, ch, size);
76+
return size;
77+
}
78+
if (ch <= 0x07FF) {
79+
size = encodeByteChar(result, 0xC0 | ((ch >> 6) & 0x1F), size);
80+
size = encodeByteChar(result, 0x80 | ((ch >> 0) & 0x3F), size);
81+
return size;
82+
}
83+
size = encodeByteChar(result, 0xE0 | ((ch >> 12) & 0x0F), size);
84+
size = encodeByteChar(result, 0x80 | ((ch >> 6) & 0x3F), size);
85+
size = encodeByteChar(result, 0x80 | ((ch >> 0) & 0x3F), size);
86+
return size;
87+
}
88+
89+
private static int encodeByteChar(char[] result, int ch, int size) {
8290
result[size++] = '%';
8391
result[size++] = HexFormat.of().toHighHexDigit(ch);
8492
result[size++] = HexFormat.of().toLowHexDigit(ch);

‎loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/net/protocol/jar/JarUrlClassLoaderTests.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,28 @@ void resolveFromNested() throws Exception {
102102
}
103103
}
104104

105+
@Test
106+
void resolveFromNestedWhenNameNeedsEncoding() throws Exception {
107+
ByteArrayOutputStream nestedJarData = new ByteArrayOutputStream();
108+
try (JarOutputStream jarOutputStream = new JarOutputStream(nestedJarData)) {
109+
jarOutputStream.putNextEntry(new JarEntry("dir with space/a#b.txt"));
110+
jarOutputStream.write(42);
111+
jarOutputStream.closeEntry();
112+
}
113+
File jarFile = new File(this.tempDir, "test.jar");
114+
try (JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile))) {
115+
writeStoredEntry(jarOutputStream, "nested.jar", nestedJarData.toByteArray());
116+
}
117+
URL url = JarUrl.create(jarFile, "nested.jar");
118+
try (JarUrlClassLoader loader = new TestJarUrlClassLoader(url)) {
119+
URL resource = loader.getResource("dir with space/a#b.txt");
120+
assertThat(resource).isNotNull();
121+
try (InputStream input = resource.openConnection().getInputStream()) {
122+
assertThat(input.read()).isEqualTo(42);
123+
}
124+
}
125+
}
126+
105127
@Test
106128
void resolveFromNestedWhenMissingReturnsNull() throws Exception {
107129
File jarFile = new File(this.tempDir, "test.jar");

‎loader/spring-boot-loader/src/test/java/org/springframework/boot/loader/net/util/UrlEncoderTests.java‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,21 @@ void encodeWhenBasicString() {
2020
assertThat(UrlEncoder.encode("a/b/C.class")).isEqualTo("a/b/C.class");
2121
}
2222

23+
@Test
24+
void encodeWhenHasSingleByteEncodedCharacters() {
25+
assertThat(UrlEncoder.encode("a b/c#d%e?f.txt")).isEqualTo("a%20b/c%23d%25e%3ff.txt");
26+
}
27+
2328
@Test
2429
void encodeWhenHasDoubleByteEncodedCharacters() {
2530
assertThat(UrlEncoder.encode("\u00e1/b/C.class")).isEqualTo("%c3%a1/b/C.class");
2631
}
2732

33+
@Test
34+
void encodeWhenHasTrippleByteEncodedCharacters() {
35+
assertThat(UrlEncoder.encode("\u6841/b/C.class")).isEqualTo("%e6%a1%81/b/C.class");
36+
}
37+
2838
@Test
2939
void encodeWhenHasMixtureOfEncodedAndUnencodedDoubleByteCharacters() {
3040
assertThat(UrlEncoder.encode("\u00e1/b/\u00c7.class")).isEqualTo("%c3%a1/b/%c3%87.class");

0 commit comments

Comments
 (0)