Skip to content

Commit c892544

Browse files
wanger26scottfrederick
authored andcommitted
Prevent long parse times for images with illegal char in tag
Update the regular expression used to parse Docker images references to prevent catastrophic backtracking when images names are long and the tag contains an illegal character. See gh-39617
1 parent 27200f3 commit c892544

File tree

4 files changed

+55
-5
lines changed
  • spring-boot-project
    • spring-boot-docker-compose/src
    • spring-boot-tools/spring-boot-buildpack-platform/src

4 files changed

+55
-5
lines changed

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/Regex.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ final class Regex implements CharSequence {
5050
private static final Regex PATH_COMPONENT;
5151
static {
5252
Regex segment = Regex.of("[a-z0-9]+");
53-
Regex separator = Regex.group("[._]|__|[-]*");
53+
Regex separator = Regex.group("[._-]{1,2}");
5454
Regex separatedSegment = Regex.group(separator, segment).oneOrMoreTimes();
5555
PATH_COMPONENT = Regex.of(segment, Regex.group(separatedSegment).zeroOrOnce());
5656
}

spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/ImageReferenceTests.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,9 +17,12 @@
1717
package org.springframework.boot.docker.compose.core;
1818

1919
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.Timeout;
21+
import org.junit.jupiter.api.Timeout.ThreadMode;
2022

2123
import static org.assertj.core.api.Assertions.assertThat;
2224
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25+
import static org.assertj.core.api.Assertions.fail;
2326

2427
/**
2528
* Tests for {@link ImageReference}.
@@ -165,4 +168,26 @@ void equalsAndHashCode() {
165168
assertThat(r1).isEqualTo(r1).isEqualTo(r2).isNotEqualTo(r3);
166169
}
167170

171+
@Test
172+
void ofSimpleNameWithSingleCharacterSuffix() {
173+
ImageReference reference = ImageReference.of("ubuntu-a");
174+
assertThat(reference.getDomain()).isEqualTo("docker.io");
175+
assertThat(reference.getName()).isEqualTo("library/ubuntu-a");
176+
assertThat(reference.getTag()).isNull();
177+
assertThat(reference.getDigest()).isNull();
178+
assertThat(reference).hasToString("docker.io/library/ubuntu-a");
179+
}
180+
181+
@Test
182+
@Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD)
183+
void ofWhenImageNameIsVeryLongAndHasIllegalCharacter() {
184+
try {
185+
ImageReference
186+
.of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234");
187+
fail("Image Reference contains an illegal character and should have thrown an IllegalArgumentException");
188+
}
189+
catch (IllegalArgumentException ignored) {
190+
}
191+
}
192+
168193
}

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/Regex.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ final class Regex implements CharSequence {
5050
private static final Regex PATH_COMPONENT;
5151
static {
5252
Regex segment = Regex.of("[a-z0-9]+");
53-
Regex separator = Regex.group("[._]|__|[-]*");
53+
Regex separator = Regex.group("[._-]{1,2}");
5454
Regex separatedSegment = Regex.group(separator, segment).oneOrMoreTimes();
5555
PATH_COMPONENT = Regex.of(segment, Regex.group(separatedSegment).zeroOrOnce());
5656
}

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageReferenceTests.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,10 +19,13 @@
1919
import java.io.File;
2020

2121
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.Timeout;
23+
import org.junit.jupiter.api.Timeout.ThreadMode;
2224

2325
import static org.assertj.core.api.Assertions.assertThat;
2426
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
2527
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
28+
import static org.assertj.core.api.Assertions.fail;
2629

2730
/**
2831
* Tests for {@link ImageReference}.
@@ -306,4 +309,26 @@ void inTaglessForm() {
306309
assertThat(updated).hasToString("docker.io/library/ubuntu");
307310
}
308311

312+
@Test
313+
void ofSimpleNameWithSingleCharacterSuffix() {
314+
ImageReference reference = ImageReference.of("ubuntu-a");
315+
assertThat(reference.getDomain()).isEqualTo("docker.io");
316+
assertThat(reference.getName()).isEqualTo("library/ubuntu-a");
317+
assertThat(reference.getTag()).isNull();
318+
assertThat(reference.getDigest()).isNull();
319+
assertThat(reference).hasToString("docker.io/library/ubuntu-a");
320+
}
321+
322+
@Test
323+
@Timeout(value = 1, threadMode = ThreadMode.SEPARATE_THREAD)
324+
void ofWhenIsVeryLongAndHasIllegalCharacter() {
325+
try {
326+
ImageReference
327+
.of("docker.io/library/this-image-has-a-long-name-with-an-invalid-tag-which-is-at-danger-of-catastrophic-backtracking:1.0.0+1234");
328+
fail("Contains an illegal character and should have thrown an IllegalArgumentException");
329+
}
330+
catch (IllegalArgumentException ignored) {
331+
}
332+
}
333+
309334
}

0 commit comments

Comments
 (0)