Home > OS >  CheckMarx issue : Race condition format flaw
CheckMarx issue : Race condition format flaw

Time:11-18

Checkmarx complains that "the file utilizes "format" that is accessed by other concurrent functionality in a way that is not thread-safe, which may result in a Race Condition over this resource. It highlights the format method. How do we resolve this?

 String endDate =
                configProperties.getDateFormatter().format(Date.from(date.plusMonths(-1L * auditTimeMonthLimit).atStartOfDay()
                        .atZone(ZoneId.systemDefault())
                        .toInstant()));

Other part of code

 private final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

 public SimpleDateFormat getDateFormatter() {
        return dateFormatter;
    }

CodePudding user response:

SimpleDateFormat is not thread safe. This is a good explanation.

There is not a lot of code in the example, but having a final instance of SimpleDateFormat implies it may be used by multiple threads.

Maybe configProperties is a global singleton? It is hard to tell, but if that code is accessed by multiple threads (including as part of a web controller or other type of web endpoint handler) and that is a single instance for every thread then you have a problem.

One possible solution (maybe not ideal, but you can translate it to something that works for you):

public SimpleDateFormat getDateFormatter() {
        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    }

There are likely better options for formatting than this, so maybe doing it entirely different would be better.

CodePudding user response:

Legacy date-time API is error-prone e.g. java.util.Date and SimpleDateFormatter aren’t thread-safe, leading to potential concurrency issues for users. It is recommended to stop using them completely and switch to the modern date-time API.

The output you are trying to achieve is already the default format of Instant and therefore, you do not need to use a formatter.

However, probably you are not familiar with the modern date-time API and therefore, for the sake of your learning, I have also demonstrated the use of DateTimeFormatter.

Demo using java.time API:

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        LocalDate date = LocalDate.now(); // Some date
        int auditTimeMonthLimit = 5; // Some value
        String endDate = date.minusMonths(auditTimeMonthLimit)
                .atStartOfDay(ZoneId.systemDefault())
                .toString();
        System.out.println(endDate);

        // In case you wanted the UTC date-time out of the local date
        endDate = date.minusMonths(auditTimeMonthLimit)
                .atStartOfDay(ZoneOffset.UTC)
                .toString();
        System.out.println(endDate);

        // In case you wanted the start date of the default time-zone to be converted
        // into the UTC date-time
        endDate = date.minusMonths(auditTimeMonthLimit)
                .atStartOfDay(ZoneId.systemDefault())
                .toInstant()
                .toString();
        System.out.println(endDate);

        // A custom format
        ZonedDateTime zdt = date.minusMonths(auditTimeMonthLimit)
                .atStartOfDay(ZoneId.systemDefault())
                .withZoneSameInstant(ZoneOffset.UTC);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
                "uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
        endDate = formatter.format(zdt);
        System.out.println(endDate);
    }
}

Output in my time-zone:

2022-06-17T00:00 01:00[Europe/London]
2022-06-17T00:00Z
2022-06-16T23:00:00Z
2022-06-16T23:00:00.000Z

Important points:

  1. I recommend you use LocalDate#minusMonths i.e. instead of using date.plusMonths(-1L * auditTimeMonthLimit), you should use date.minusMonths(auditTimeMonthLimit).
  2. 'Z' is not the same as Z.
  3. For your use case, I recommend you use LocalDate#atStartOfDay(ZoneId zone) instead of the non-parametrized LocalDate#atStartOfDay. This will make you

Learn more about the modern Date-Time API from Trail: Date Time.

  • Related