Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions core/src/main/java/org/apache/struts2/components/Include.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;

/**
Expand Down Expand Up @@ -203,28 +204,30 @@ public static String getContextRelativePath(ServletRequest request, String relat
// .. is illegal in an absolute path according to the Servlet Spec and will cause
// known problems on Orion application servers.
if (returnValue.contains("..")) {
Stack<String> stack = new Stack<>();
Deque<String> segments = new ArrayDeque<>();
StringTokenizer pathParts = new StringTokenizer(returnValue.replace('\\', '/'), "/");

while (pathParts.hasMoreTokens()) {
String part = pathParts.nextToken();

if (!part.equals(".")) {
if (part.equals("..")) {
stack.pop();
if (!segments.isEmpty()) {
segments.pop();
}
} else {
stack.push(part);
segments.push(part);
}
}
}

StringBuilder flatPathBuffer = new StringBuilder();

for (int i = 0; i < stack.size(); i++) {
flatPathBuffer.append("/").append(stack.elementAt(i));
for (String segment : segments) {
flatPathBuffer.append("/").append(segment);
}

returnValue = flatPathBuffer.toString();
returnValue = flatPathBuffer.length() > 0 ? flatPathBuffer.toString() : "/";
}

return returnValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,18 @@ public void testIncludeRelative2Dots_clearTagStateSet() throws Exception {
strutsBodyTagsAreReflectionEqual(tag, freshTag));
}

public void testGetContextRelativePathExcessDotDot() {
// Excess ".." segments beyond root should be silently clamped, not throw EmptyStackException
String result = Include.getContextRelativePath(request, "/../../../other/resource.jsp");
assertEquals("/other/resource.jsp", result);
}

public void testGetContextRelativePathAllDotDot() {
// All segments are ".." - should resolve to root
String result = Include.getContextRelativePath(request, "/a/../../..");
assertEquals("/", result);
}

public void testIncludeSetUseResponseEncodingTrue() throws Exception {
// TODO: If possible in future mock-test an actual content-includes with various encodings
// while setting the response encoding to match. Doesn't appear to be possible
Expand Down