CodeQL queries 1.23

Skip to end of metadata
Go to start of metadata

Name: Hard-coded Japanese era start date

Description: Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates.

ID: cpp/japanese-era/exact-era-date

Kind: problem

Severity: warning

Precision: medium

Query: JapaneseEraDate.ql
/**
 * @name Hard-coded Japanese era start date
 * @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates.
 * @kind problem
 * @problem.severity warning
 * @id cpp/japanese-era/exact-era-date
 * @precision medium
 * @tags reliability
 *       japanese-era
 */

import cpp
import semmle.code.cpp.commons.DateTime

predicate assignedYear(Struct s, YearFieldAccess year, int value) {
  exists(Operation yearAssignment |
    s.getAField().getAnAccess() = year and
    yearAssignment.getAnOperand() = year and
    yearAssignment.getAnOperand().getValue().toInt() = value
  )
}

predicate assignedMonth(Struct s, MonthFieldAccess month, int value) {
  exists(Operation monthAssignment |
    s.getAField().getAnAccess() = month and
    monthAssignment.getAnOperand() = month and
    monthAssignment.getAnOperand().getValue().toInt() = value
  )
}

predicate assignedDay(Struct s, DayFieldAccess day, int value) {
  exists(Operation dayAssignment |
    s.getAField().getAnAccess() = day and
    dayAssignment.getAnOperand() = day and
    dayAssignment.getAnOperand().getValue().toInt() = value
  )
}

predicate eraDate(int year, int month, int day) {
  year = 1989 and month = 1 and day = 8
  or
  year = 2019 and month = 5 and day = 1
}

predicate badStructInitialization(Element target, string message) {
  exists(
    StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day,
    int yearValue, int monthValue, int dayValue
  |
    eraDate(yearValue, monthValue, dayValue) and
    assignedYear(s, year, yearValue) and
    assignedMonth(s, month, monthValue) and
    assignedDay(s, day, dayValue) and
    target = year and
    message = "A time struct that is initialized with exact Japanese calendar era start date."
  )
}

predicate badCall(Element target, string message) {
  exists(Call cc, int i |
    eraDate(cc.getArgument(i).getValue().toInt(), cc.getArgument(i + 1).getValue().toInt(),
      cc.getArgument(i + 2).getValue().toInt()) and
    target = cc and
    message = "Call that appears to have hard-coded Japanese era start date as parameter."
  )
}

from Element target, string message
where
  badStructInitialization(target, message) or
  badCall(target, message)
select target, message

When eras change, date and time conversions that rely on a hard-coded era start date need to be reviewed. Conversions relying on Japanese dates in the current era can produce an ambiguous date. The values for the current Japanese era dates should be read from a source that will be updated, such as the Windows registry.

References