Skip to content
Merged
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
2 changes: 2 additions & 0 deletions java/change-notes/2021-03-05-regex-utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lgtm,codescanning
* Added models for Apache Commons Lang's `RegExUtils` class. This means that any query that tracks tainted data may return additional results in cases where a `RegExUtils` transformation is part of the path from source to sink.
20 changes: 20 additions & 0 deletions java/ql/src/semmle/code/java/frameworks/apache/Lang.qll
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,23 @@ private class ApacheStrSubstitutorModel extends SummaryModelCsv {
]
}
}

/**
* Taint-propagating models for `RegexUtils`.
*/
private class ApacheRegExUtilsModel extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import org.apache.commons.lang3.RegExUtils;
import java.util.regex.Pattern;

public class RegExUtilsTest {
String taint() { return "tainted"; }

void sink(Object o) {}

void test() throws Exception {
Pattern cleanPattern = Pattern.compile("clean");
Pattern taintedPattern = Pattern.compile(taint());

sink(RegExUtils.removeAll(taint(), cleanPattern)); // $hasTaintFlow
sink(RegExUtils.removeAll(taint(), "clean")); // $hasTaintFlow
sink(RegExUtils.removeFirst(taint(), cleanPattern)); // $hasTaintFlow
sink(RegExUtils.removeFirst(taint(), "clean")); // $hasTaintFlow
sink(RegExUtils.removePattern(taint(), "clean")); // $hasTaintFlow
sink(RegExUtils.replaceAll(taint(), cleanPattern, "replacement")); // $hasTaintFlow
sink(RegExUtils.replaceAll(taint(), "clean", "replacement")); // $hasTaintFlow
sink(RegExUtils.replaceFirst(taint(), cleanPattern, "replacement")); // $hasTaintFlow
sink(RegExUtils.replaceFirst(taint(), "clean", "replacement")); // $hasTaintFlow
sink(RegExUtils.replacePattern(taint(), "clean", "replacement")); // $hasTaintFlow
sink(RegExUtils.replaceAll("original", cleanPattern, taint())); // $hasTaintFlow
sink(RegExUtils.replaceAll("original", "clean", taint())); // $hasTaintFlow
sink(RegExUtils.replaceFirst("original", cleanPattern, taint())); // $hasTaintFlow
sink(RegExUtils.replaceFirst("original", "clean", taint())); // $hasTaintFlow
sink(RegExUtils.replacePattern("original", "clean", taint())); // $hasTaintFlow
// Subsequent calls don't propagate taint, as regex search patterns don't propagate to the return value.
sink(RegExUtils.removeAll("original", taintedPattern));
sink(RegExUtils.removeAll("original", taint()));
sink(RegExUtils.removeFirst("original", taintedPattern));
sink(RegExUtils.removeFirst("original", taint()));
sink(RegExUtils.removePattern("original", taint()));
sink(RegExUtils.replaceAll("original", taintedPattern, "replacement"));
sink(RegExUtils.replaceAll("original", taint(), "replacement"));
sink(RegExUtils.replaceFirst("original", taintedPattern, "replacement"));
sink(RegExUtils.replaceFirst("original", taint(), "replacement"));
sink(RegExUtils.replacePattern("original", taint(), "replacement"));
sink(RegExUtils.replaceAll("original", taintedPattern, "replacement"));
sink(RegExUtils.replaceAll("original", taint(), "replacement"));
sink(RegExUtils.replaceFirst("original", taintedPattern, "replacement"));
sink(RegExUtils.replaceFirst("original", taint(), "replacement"));
sink(RegExUtils.replacePattern("original", taint(), "replacement"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3;

import java.util.regex.Pattern;

public class RegExUtils {
public static String removeAll(final String text, final Pattern regex) {
return null;
}

public static String removeAll(final String text, final String regex) {
return null;
}

public static String removeFirst(final String text, final Pattern regex) {
return null;
}

public static String removeFirst(final String text, final String regex) {
return null;
}

public static String removePattern(final String text, final String regex) {
return null;
}

public static String replaceAll(final String text, final Pattern regex, final String replacement) {
return null;
}

public static String replaceAll(final String text, final String regex, final String replacement) {
return null;
}

public static String replaceFirst(final String text, final Pattern regex, final String replacement) {
return null;
}

public static String replaceFirst(final String text, final String regex, final String replacement) {
return null;
}

public static String replacePattern(final String text, final String regex, final String replacement) {
return null;
}

}