Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-3457

Printf-style format strings should be used correctly

    XMLWordPrintable

    Details

    • Type: Code Smell Detection
    • Status: Active
    • Resolution: Unresolved
    • Labels:
    • Message:
      XXXX
    • Default Severity:
      Major
    • Impact:
      Low
    • Likelihood:
      High
    • Default Quality Profiles:
      Sonar way
    • Covered Languages:
      C#, C, C++, Java, Objective-C, Python
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      10min
    • Analysis Scope:
      Main Sources, Test Sources
    • CERT:
      FIO47-C.
    • ReSharper:
      RedundantStringFormatCall

      Description

      Because printf-style format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that result in the wrong strings being created. This rule statically validates the correlation of printf-style format strings to their arguments when calling the format(...) methods of java.util.Formatter, java.lang.String, java.io.PrintStream, MessageFormat, and java.io.PrintWriter classes and the printf(...) methods of java.io.PrintStream or java.io.PrintWriter classes.

      Noncompliant Code Example

      String.format("First {0} and then {1}", "foo", "bar");  //Noncompliant. Looks like there is a confusion with the use of {{java.text.MessageFormat}}, parameters "foo" and "bar" will be simply ignored here
      String.format("Display %3$d and then %d", 1, 2, 3);   //Noncompliant; the second argument '2' is unused
      String.format("Too many arguments %d and %d", 1, 2, 3);  //Noncompliant; the third argument '3' is unused
      String.format("First Line\n");   //Noncompliant; %n should be used in place of \n to produce the platform-specific line separator
      String.format("Is myObject null ? %b", myObject);   //Noncompliant; when a non-boolean argument is formatted with %b, it prints true for any nonnull value, and false for null. Even if intended, this is misleading. It's better to directly inject the boolean value (myObject == null in this case)
      String.format("value is " + value); // Noncompliant
      String s = String.format("string without arguments"); // Noncompliant
      
      MessageFormat.format("Result '{0}'.", value); // Noncompliant; String contains no format specifiers. (quote are discarding format specifiers)
      MessageFormat.format("Result {0}.", value, value);  // Noncompliant; 2nd argument is not used
      MessageFormat.format("Result {0}.", myObject.toString()); // Noncompliant; no need to call toString() on objects
      
      java.util.Logger logger;
      logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject.toString()); // Noncompliant; no need to call toString() on objects
      logger.log(java.util.logging.Level.SEVERE, "Result.", new Exception()); // compliant, parameter is an exception
      logger.log(java.util.logging.Level.SEVERE, "Result '{0}'", 14); // Noncompliant - String contains no format specifiers.
      logger.log(java.util.logging.Level.SEVERE, "Result " + param, exception); // Noncompliant; Lambda should be used to differ string concatenation.
      
      org.slf4j.Logger slf4jLog;
      org.slf4j.Marker marker;
      
      slf4jLog.debug(marker, "message {}");
      slf4jLog.debug(marker, "message", 1); // Noncompliant - String contains no format specifiers.
      
      org.apache.logging.log4j.Logger log4jLog;
      log4jLog.debug("message", 1); // Noncompliant - String contains no format specifiers.
      

      Compliant Solution

      String.format("First %s and then %s", "foo", "bar");
      String.format("Display %2$d and then %d", 1, 3);
      String.format("Too many arguments %d %d", 1, 2);
      String.format("First Line%n");
      String.format("Is myObject null ? %b", myObject == null);
      String.format("value is %d", value);
      String s = "string without arguments"; 
      
      MessageFormat.format("Result {0}.", value);
      MessageFormat.format("Result '{0}'  =  {0}", value);
      MessageFormat.format("Result {0}.", myObject);
      
      java.util.Logger logger;
      logger.log(java.util.logging.Level.SEVERE, "Result {0}.", myObject);
      logger.log(java.util.logging.Level.SEVERE, "Result {0}'", 14);
      logger.log(java.util.logging.Level.SEVERE, exception, () -> "Result " + param);
      
      org.slf4j.Logger slf4jLog;
      org.slf4j.Marker marker;
      
      slf4jLog.debug(marker, "message {}");
      slf4jLog.debug(marker, "message {}", 1);
      
      org.apache.logging.log4j.Logger log4jLog;
      log4jLog.debug("message {}", 1);
      

      See

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              ann.campbell.2 Ann Campbell
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated: