Skip to content

Commit ba3ec50

Browse files
authored
Merge pull request #1467 from geoffw0/dates-cleanup1
CPP: Follow-up for Mishandling Japanese Era and Leap Year in calculations
2 parents 196ad76 + 717522f commit ba3ec50

13 files changed

+175
-158
lines changed

cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<references>
1313
<li>
14-
<a href="https://blogs.msdn.microsoft.com/shawnste/2018/04/12/the-japanese-calendars-y2k-moment/">The Japanese Calendars Y2K Moment</a>.
14+
<a href="https://blogs.msdn.microsoft.com/shawnste/2018/04/12/the-japanese-calendars-y2k-moment/">The Japanese Calendar's Y2K Moment</a>.
1515
</li>
1616
</references>
1717
</qhelp>

cpp/ql/src/Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
*/
1111

1212
import cpp
13+
1314
from Call cc, int i
14-
where cc.getArgument(i).getValue().toInt() = 1989 and
15-
cc.getArgument(i+1).getValue().toInt() = 1 and
16-
cc.getArgument(i+2).getValue().toInt() = 8
17-
select cc, "Call that appears to have hard-coded Japanese era start date as parameter."
15+
where
16+
cc.getArgument(i).getValue().toInt() = 1989 and
17+
cc.getArgument(i + 1).getValue().toInt() = 1 and
18+
cc.getArgument(i + 2).getValue().toInt() = 8
19+
select cc, "Call that appears to have hard-coded Japanese era start date as parameter."

cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<references>
1313
<li>
14-
<a href="https://blogs.msdn.microsoft.com/shawnste/2018/04/12/the-japanese-calendars-y2k-moment/">The Japanese Calendars Y2K Moment</a>.
14+
<a href="https://blogs.msdn.microsoft.com/shawnste/2018/04/12/the-japanese-calendars-y2k-moment/">The Japanese Calendar's Y2K Moment</a>.
1515
</li>
1616
</references>
1717
</qhelp>

cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@
44
* @kind problem
55
* @problem.severity warning
66
* @id cpp/japanese-era/struct-with-exact-era-date
7-
* @precision medium
87
* @tags reliability
98
* japanese-era
109
*/
1110

1211
import cpp
13-
1412
import semmle.code.cpp.commons.DateTime
1513

16-
from StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day, Operation yearAssignment, Operation monthAssignment, Operation dayAssignment
17-
where s.getAField().getAnAccess () = year and yearAssignment.getAnOperand() = year and yearAssignment.getAnOperand().getValue().toInt() = 1989 and
18-
s.getAField().getAnAccess () = month and monthAssignment.getAnOperand() = month and monthAssignment.getAnOperand().getValue().toInt() = 1 and
19-
s.getAField().getAnAccess () = day and dayAssignment.getAnOperand() = day and dayAssignment.getAnOperand().getValue().toInt() = 8
14+
from
15+
StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day,
16+
Operation yearAssignment, Operation monthAssignment, Operation dayAssignment
17+
where
18+
s.getAField().getAnAccess() = year and
19+
yearAssignment.getAnOperand() = year and
20+
yearAssignment.getAnOperand().getValue().toInt() = 1989 and
21+
s.getAField().getAnAccess() = month and
22+
monthAssignment.getAnOperand() = month and
23+
monthAssignment.getAnOperand().getValue().toInt() = 1 and
24+
s.getAField().getAnAccess() = day and
25+
dayAssignment.getAnOperand() = day and
26+
dayAssignment.getAnOperand().getValue().toInt() = 8
2027
select year, "A time struct that is initialized with exact Japanese calendar era start date."

cpp/ql/src/Likely Bugs/Leap Year/Adding365daysPerYear.qhelp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ of days. Alternatively, use an established library routine that already contain
1515
</recommendation>
1616

1717
<references>
18-
<include src="LeapYearReferences.qhelp" />
18+
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
19+
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
20+
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
1921
</references>
2022
</qhelp>

cpp/ql/src/Likely Bugs/Leap Year/Adding365daysPerYear.ql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
* @name Year field changed using an arithmetic operation is used on an unchecked time conversion function
33
* @description A year field changed using an arithmetic operation is used on a time conversion function, but the return value of the function is not checked for success or failure.
44
* @kind problem
5-
* @problem.severity error
5+
* @problem.severity warning
66
* @id cpp/leap-year/adding-365-days-per-year
7-
* @precision high
7+
* @precision medium
88
* @tags security
99
* leap-year
1010
*/
@@ -15,6 +15,6 @@ import semmle.code.cpp.dataflow.DataFlow
1515

1616
from Expr source, Expr sink, PossibleYearArithmeticOperationCheckConfiguration config
1717
where config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(sink))
18-
select sink, "This arithmetic operation $@ uses a constant value of 365 ends up modifying the date/time located at $@, without considering leap year scenarios."
19-
, source, source.toString()
20-
, sink, sink.toString()
18+
select sink,
19+
"This arithmetic operation $@ uses a constant value of 365 ends up modifying the date/time located at $@, without considering leap year scenarios.",
20+
source, source.toString(), sink, sink.toString()

cpp/ql/src/Likely Bugs/Leap Year/LeapYearReferences.qhelp

Lines changed: 0 additions & 10 deletions
This file was deleted.

cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.qhelp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
</example>
2323

2424
<references>
25-
<include src="LeapYearReferences.qhelp" />
25+
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
26+
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
27+
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
2628
</references>
2729
</qhelp>

cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,63 @@
22
* @name Year field changed using an arithmetic operation without checking for leap year
33
* @description A field that represents a year is being modified by an arithmetic operation, but no proper check for leap years can be detected afterwards.
44
* @kind problem
5-
* @problem.severity error
5+
* @problem.severity warning
66
* @id cpp/leap-year/unchecked-after-arithmetic-year-modification
7-
* @precision high
7+
* @precision medium
88
* @tags security
99
* leap-year
1010
*/
1111

1212
import cpp
1313
import LeapYear
1414

15-
from Variable var, LeapYearFieldAccess yfa
15+
from Variable var, LeapYearFieldAccess yfa
1616
where
17-
exists(VariableAccess va |
18-
yfa.getQualifier() = va
19-
and var.getAnAccess() = va
20-
// The year is modified with an arithmetic operation. Avoid values that are likely false positives
21-
and yfa.isModifiedByArithmeticOperationNotForNormalization()
22-
// Avoid false positives
23-
and not (
24-
// If there is a local check for leap year after the modification
25-
exists( LeapYearFieldAccess yfacheck |
26-
yfacheck.getQualifier() = var.getAnAccess()
27-
and yfacheck.isUsedInCorrectLeapYearCheck()
28-
and yfacheck = yfa.getASuccessor*()
29-
)
30-
// If there is a data flow from the variable that was modified to a function that seems to check for leap year
31-
or exists(VariableAccess source,
32-
ChecksForLeapYearFunctionCall fc,
33-
LeapYearCheckConfiguration config |
34-
source = var.getAnAccess()
35-
and config.hasFlow( DataFlow::exprNode(source), DataFlow::exprNode(fc.getAnArgument()))
36-
)
37-
// If there is a data flow from the field that was modified to a function that seems to check for leap year
38-
or exists(VariableAccess vacheck,
39-
YearFieldAccess yfacheck,
40-
ChecksForLeapYearFunctionCall fc,
41-
LeapYearCheckConfiguration config |
42-
vacheck = var.getAnAccess()
43-
and yfacheck.getQualifier() = vacheck
44-
and config.hasFlow( DataFlow::exprNode(yfacheck), DataFlow::exprNode(fc.getAnArgument()))
45-
)
46-
// If there is a successor or predecessor that sets the month = 1
47-
or exists(MonthFieldAccess mfa, AssignExpr ae |
48-
mfa.getQualifier() = var.getAnAccess()
49-
and mfa.isModified()
50-
and (mfa = yfa.getASuccessor*()
51-
or yfa = mfa.getASuccessor*())
52-
and ae = mfa.getEnclosingElement()
53-
and ae.getAnOperand().getValue().toInt() = 1
54-
)
55-
)
56-
)
57-
select yfa
58-
, "Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found.", yfa.getTarget(), yfa.getTarget().toString(), var, var.toString()
17+
exists(VariableAccess va |
18+
yfa.getQualifier() = va and
19+
var.getAnAccess() = va and
20+
// The year is modified with an arithmetic operation. Avoid values that are likely false positives
21+
yfa.isModifiedByArithmeticOperationNotForNormalization() and
22+
// Avoid false positives
23+
not (
24+
// If there is a local check for leap year after the modification
25+
exists(LeapYearFieldAccess yfacheck |
26+
yfacheck.getQualifier() = var.getAnAccess() and
27+
yfacheck.isUsedInCorrectLeapYearCheck() and
28+
yfacheck = yfa.getASuccessor*()
29+
)
30+
or
31+
// If there is a data flow from the variable that was modified to a function that seems to check for leap year
32+
exists(
33+
VariableAccess source, ChecksForLeapYearFunctionCall fc, LeapYearCheckConfiguration config
34+
|
35+
source = var.getAnAccess() and
36+
config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(fc.getAnArgument()))
37+
)
38+
or
39+
// If there is a data flow from the field that was modified to a function that seems to check for leap year
40+
exists(
41+
VariableAccess vacheck, YearFieldAccess yfacheck, ChecksForLeapYearFunctionCall fc,
42+
LeapYearCheckConfiguration config
43+
|
44+
vacheck = var.getAnAccess() and
45+
yfacheck.getQualifier() = vacheck and
46+
config.hasFlow(DataFlow::exprNode(yfacheck), DataFlow::exprNode(fc.getAnArgument()))
47+
)
48+
or
49+
// If there is a successor or predecessor that sets the month = 1
50+
exists(MonthFieldAccess mfa, AssignExpr ae |
51+
mfa.getQualifier() = var.getAnAccess() and
52+
mfa.isModified() and
53+
(
54+
mfa = yfa.getASuccessor*() or
55+
yfa = mfa.getASuccessor*()
56+
) and
57+
ae = mfa.getEnclosingElement() and
58+
ae.getAnOperand().getValue().toInt() = 1
59+
)
60+
)
61+
)
62+
select yfa,
63+
"Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found.",
64+
yfa.getTarget(), yfa.getTarget().toString(), var, var.toString()

cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.qhelp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<p>When using a function that transforms a date structure, and the year on the input argument for the API has been manipulated, it is important to check for the return value of the function to make sure it succeeded.</p>
99
<p>Otherwise, the function may have failed, and the output parameter may contain invalid data that can cause any number of problems on the affected system.</p>
1010
<p>The following is a list of the functions that this query covers:</p>
11-
<list>
11+
<ul>
1212
<li><code>FileTimeToSystemTime</code></li>
1313
<li><code>SystemTimeToFileTime</code></li>
1414
<li><code>SystemTimeToTzSpecificLocalTime</code></li>
@@ -18,7 +18,7 @@
1818
<li><code>RtlLocalTimeToSystemTime</code></li>
1919
<li><code>RtlTimeToSecondsSince1970</code></li>
2020
<li><code>_mkgmtime</code></li>
21-
</list>
21+
</ul>
2222

2323
</overview>
2424
<recommendation>
@@ -34,6 +34,8 @@
3434
</example>
3535

3636
<references>
37-
<include src="LeapYearReferences.qhelp" />
37+
<li>U.S. Naval Observatory Website - <a href="https://aa.usno.navy.mil/faq/docs/calendars.php"> Introduction to Calendars</a></li>
38+
<li>Wikipedia - <a href="https://en.wikipedia.org/wiki/Leap_year_bug"> Leap year bug</a> </li>
39+
<li>Microsoft Azure blog - <a href="https://azure.microsoft.com/en-us/blog/is-your-code-ready-for-the-leap-year/"> Is your code ready for the leap year?</a> </li>
3840
</references>
3941
</qhelp>

0 commit comments

Comments
 (0)