Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch order of literals to prevent NullPointerException #868

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

citizenjosh
Copy link

This change defensively switches the order of literals in comparison expressions to ensure that no null pointer exceptions are unexpectedly thrown. Runtime exceptions especially can cause exceptional and unexpected code paths to be taken, and this can result in unexpected behavior.

Both simple vulnerabilities (like information disclosure) and complex vulnerabilities (like business logic flaws) can take advantage of these unexpected code paths.

Our changes look something like this:

  String fieldName = header.getFieldName();
  String fieldValue = header.getFieldValue();
- if(fieldName.equals("requestId")) {
+ if("requestId".equals(fieldName)) {
    logRequest(fieldValue);
  }
More reading

Powered by: pixeebot (codemod ID: pixee:java/switch-literal-first)

pixeebot and others added 2 commits January 20, 2024 01:21
…-java/switch-literal-first

Switch order of literals to prevent NullPointerException
@CLAassistant
Copy link

CLAassistant commented Jan 23, 2024

CLA assistant check
All committers have signed the CLA.

Copy link
Collaborator

@ibodrov ibodrov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4/9

@@ -77,7 +77,7 @@ public static <T> T handle(ObjectMapper objectMapper,

private static boolean isJsonMime(String mime) {
String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
return mime != null && (mime.matches(jsonMime) || "*/*".equals(mime));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless. Non-null value here is already asserted.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this change is to be proactively defensive. Though it may be negligibly faster to run this way, it also conforms to a best practice and makes the code easier to read. Also, since the behavior is otherwise equivalent, there is no cost to this change.

@@ -82,8 +82,8 @@ private String checkScope(String scope) {
return null;
}

if (!scope.equalsIgnoreCase("ORG")
&& !scope.equalsIgnoreCase("PROJECT")) {
if (!"ORG".equalsIgnoreCase(scope)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked before.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this change is to be proactively defensive. Though it may be negligibly faster to run this way, it also conforms to a best practice and makes the code easier to read. Also, since the behavior is otherwise equivalent, there is no cost to this change.

@@ -60,7 +60,7 @@ public void checkPermission(Permission perm) {
String path = perm.getName();

// allow all local paths
if (!path.startsWith("/") && !path.equals(ALL_FILES_TOKEN)) {
if (!path.startsWith("/") && !ALL_FILES_TOKEN.equals(path)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot be null here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this change is to be proactively defensive. Though it may be negligibly faster to run this way, it also conforms to a best practice and makes the code easier to read. Also, since the behavior is otherwise equivalent, there is no cost to this change.

@@ -278,7 +278,7 @@ default Set<VariableMapping> getVarMap(Map<String, Object> options, String key)
result.add(new VariableMapping(null, sourceExpr, sourceValue, target, true));
}

if (key.equals("in") && getWithItems(options) != null) {
if ("in".equals(key) && getWithItems(options) != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this change is to be proactively defensive. Though it may be negligibly faster to run this way, it also conforms to a best practice and makes the code easier to read. Also, since the behavior is otherwise equivalent, there is no cost to this change.

@@ -121,7 +121,7 @@ private static void validateSpec(Trigger t, List<String> errors) {

private static void validateTimezone(Trigger t, List<String> errors) {
String triggerName = t.name();
if (!triggerName.equals("cron")) {
if (!"cron".equals(triggerName)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe useful?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this change is to be proactively defensive. Though it may be negligibly faster to run this way, it also conforms to a best practice and makes the code easier to read. Also, since the behavior is otherwise equivalent, there is no cost to this change.

@@ -260,7 +260,7 @@ private UserType assertUserType(String username, String domain, UserType type) {
}

private UserType assertSsoUserType(UserPrincipal u, UserType type) {
if (u.getRealm().equals(SSO_REALM_NAME)) {
if (SSO_REALM_NAME.equals(u.getRealm())) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not.

@@ -118,7 +118,7 @@ public String getConfirmationMessage() {

@Override
public void setUp() {
if (this.skip.equals("true")) {
if ("true".equals(this.skip)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

@@ -70,7 +70,7 @@ public AuthenticationToken createToken(ServletRequest request, ServletResponse r
String header = req.getHeader(AUTHORIZATION_HEADER);
if (header != null) {
String[] as = header.split(" ");
if (as.length != 2 || !as[0].equals(HEADER_PREFIX)) {
if (as.length != 2 || !HEADER_PREFIX.equals(as[0])) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot be null.

Copy link
Author

@citizenjosh citizenjosh Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this change is to be proactively defensive. Though it may be negligibly faster to run this way, it also conforms to a best practice and makes the code easier to read. Also, since the behavior is otherwise equivalent, there is no cost to this change.

@@ -186,7 +186,7 @@ private static Map<String, String> getDependencyVersionsFromFile(RunnerJob job)
}

private static boolean isLatestVersion(String v) {
return v.equalsIgnoreCase("latest");
return "latest".equalsIgnoreCase(v);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

@ibodrov
Copy link
Collaborator

ibodrov commented Jan 23, 2024

This bot need more training.

@drdavella
Copy link

drdavella commented Mar 1, 2024

@ibodrov thanks for the feedback on this PR!

I'm a maintainer of @pixeebot and just wanted to point out that @pixeebot is not actually using AI to make this change. We use an OSS framework called Codemodder: https://github.com/pixee/codemodder-java

This particular codemod is implemented here: https://github.com/pixee/codemodder-java/blob/main/core-codemods/src/main/java/io/codemodder/codemods/SwitchLiteralFirstComparisonsCodemod.java

A big part of our philosophy is to introduce proactively defensive changes that have no downside. In this particular case, it seems you've identified four places where the code potentially benefits from this hardening and five places where maybe it's not as obviously useful.

Given that, I'm curious whether you see any downside to merging the code as-is given that it's a defensive change that also reflects a best practice? Your feedback is appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants