Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java safe String.format and escaping %

Tags:

java

I'm using String.format method of Java API to log something. My method is like:

public static void log(String message, Object... params){
    System.out.println(String.format(message, params));
}

However the problem is, if the user sends a message that has % character somewhere in it, it throws exception. Here's a scenario:

log("SELECT * FROM my WHERE name like '%six%'");

and Java looks for something to replace %s (that's ok) and %' (oops). I want to fix that. Because there there are no params and %s will be lost and %' causes exception.

One solution can be message.replace("%", "%%") but I'm not sure it is an elegant solution or not.

like image 719
ahmet alp balkan Avatar asked Feb 22 '23 23:02

ahmet alp balkan


2 Answers

log has no idea whether a given % is meant as a format specifier or as a percent sign. Consider the following example:

log("%s%s", "test");

Is that "test%s", "%stest", or an error?

Therefore, the problem will have to be addressed at the call site:

log(escape("SELECT * FROM my WHERE name like '%six%'"));

where escape() is a function you'll need to write that'll replace all % with %%.

Alternatively, the following can be used at the call site:

log("%s", "SELECT * FROM my WHERE name like '%six%'");
like image 143
NPE Avatar answered Feb 25 '23 17:02

NPE


A simple solution for the most likely misuse (using %s or % somewhere in the String but providing no parameters) would be to provide a no-params overload to your method in addition to your original method:

public static void log(String message) {
  System.out.println(message);
}

Alternatively you can dynamically try to detect the no-params case, but that's a bit more work:

public static void log(String message, Object... params) {
  final String output;
  if (params == null || params.length = 0) {
    output = message;
  } else {
    output = String.format(message, params);
  }
  System.out.println(output);
}
like image 20
Joachim Sauer Avatar answered Feb 25 '23 17:02

Joachim Sauer