Skip to content

Commit eedca61

Browse files
Merge pull request #878 from github/michaelrfairhurst/implement-missing-sin-precision-amendment
Implement missing amendment for directive 4-11 from misra C 2012 amendment 3
2 parents 2fad698 + d3e1704 commit eedca61

File tree

8 files changed

+157
-1
lines changed

8 files changed

+157
-1
lines changed

Diff for: amendments.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
language,standard,amendment,rule_id,supportable,implementation_category,implemented,difficulty
22
c,MISRA-C-2012,Amendment3,DIR-4-6,Yes,Expand,Yes,Easy
33
c,MISRA-C-2012,Amendment3,DIR-4-9,Yes,Refine,Yes,Easy
4-
c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,No,Import
4+
c,MISRA-C-2012,Amendment3,DIR-4-11,Yes,Refine,Yes,Import
55
c,MISRA-C-2012,Amendment3,RULE-1-4,Yes,Replace,Yes,Easy
66
c,MISRA-C-2012,Amendment3,RULE-10-1,Yes,Replace,Yes,Easy
77
c,MISRA-C-2012,Amendment3,RULE-10-3,Yes,Refine,Yes,Easy
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @id c/misra/low-precision-periodic-trigonometric-function-call
3+
* @name DIR-4-11: The validity of values passed to trigonometric functions shall be checked
4+
* @description Trigonometric periodic functions have significantly less precision when called with
5+
* large floating-point values.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity warning
9+
* @tags external/misra/id/dir-4-11
10+
* correctness
11+
* external/misra/c/2012/third-edition-first-revision
12+
* external/misra/c/2012/amendment3
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
19+
20+
float getMaxAllowedAbsoluteValue(FloatingPointType t, string description) {
21+
if t.getSize() <= 4
22+
then (
23+
// Per MISRA, assume k=1 for float types.
24+
result = 3.15 and description = "pi"
25+
) else (
26+
// Allow k=10 for doubles, as the standard allows for a larger range depending on the
27+
// implementation, application, and precision goals.
28+
result = 10 * 3.15 and description = "10 * pi"
29+
)
30+
}
31+
32+
from FunctionCall fc, Expr argument, float maxValue, float maxAllowedValue, string maxAllowedStr
33+
where
34+
not isExcluded(fc, ContractsPackage::lowPrecisionPeriodicTrigonometricFunctionCallQuery()) and
35+
fc.getTarget().getName() = ["sin", "cos", "tan"] and
36+
argument = fc.getArgument(0) and
37+
maxValue = rank[1](float bound | bound = [lowerBound(argument), upperBound(argument)].abs()) and
38+
maxAllowedValue = getMaxAllowedAbsoluteValue(argument.getType(), maxAllowedStr) and
39+
maxValue > maxAllowedValue
40+
select fc,
41+
"Call to periodic trigonometric function " + fc.getTarget().getName() +
42+
" with maximum argument absolute value of " + maxValue.toString() +
43+
", which exceeds the recommended " + "maximum of " + maxAllowedStr + "."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
| test.c:32:5:32:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. |
2+
| test.c:33:5:33:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. |
3+
| test.c:34:5:34:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. |
4+
| test.c:38:5:38:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. |
5+
| test.c:39:5:39:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. |
6+
| test.c:40:5:40:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 31.4, which exceeds the recommended maximum of pi. |
7+
| test.c:49:5:49:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. |
8+
| test.c:50:5:50:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. |
9+
| test.c:51:5:51:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. |
10+
| test.c:52:5:52:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. |
11+
| test.c:53:5:53:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. |
12+
| test.c:54:5:54:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. |
13+
| test.c:55:5:55:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. |
14+
| test.c:56:5:56:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. |
15+
| test.c:57:5:57:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of pi. |
16+
| test.c:58:5:58:7 | call to sin | Call to periodic trigonometric function sin with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. |
17+
| test.c:59:5:59:7 | call to cos | Call to periodic trigonometric function cos with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. |
18+
| test.c:60:5:60:7 | call to tan | Call to periodic trigonometric function tan with maximum argument absolute value of 314, which exceeds the recommended maximum of 10 * pi. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/DIR-4-11/LowPrecisionPeriodicTrigonometricFunctionCall.ql

Diff for: c/misra/test/rules/DIR-4-11/test.c

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <math.h>
2+
void f(int x) {
3+
float f1 = 0.0f;
4+
double d1 = 0.0f;
5+
sin(f1); // COMPLIANT
6+
cos(f1); // COMPLIANT
7+
tan(f1); // COMPLIANT
8+
sin(d1); // COMPLIANT
9+
cos(d1); // COMPLIANT
10+
tan(d1); // COMPLIANT
11+
12+
if (x < 10) {
13+
f1 += 3.14;
14+
d1 += 3.14;
15+
sin(f1); // COMPLIANT
16+
cos(f1); // COMPLIANT
17+
tan(f1); // COMPLIANT
18+
sin(d1); // COMPLIANT
19+
cos(d1); // COMPLIANT
20+
tan(d1); // COMPLIANT
21+
sin(-f1); // COMPLIANT
22+
cos(-f1); // COMPLIANT
23+
tan(-f1); // COMPLIANT
24+
sin(-d1); // COMPLIANT
25+
cos(-d1); // COMPLIANT
26+
tan(-d1); // COMPLIANT
27+
}
28+
29+
if (x < 20) {
30+
f1 = 3.14 * 10;
31+
d1 = 3.14 * 10;
32+
sin(f1); // NON-COMPLIANT
33+
cos(f1); // NON-COMPLIANT
34+
tan(f1); // NON-COMPLIANT
35+
sin(d1); // COMPLIANT
36+
cos(d1); // COMPLIANT
37+
tan(d1); // COMPLIANT
38+
sin(-f1); // NON-COMPLIANT
39+
cos(-f1); // NON-COMPLIANT
40+
tan(-f1); // NON-COMPLIANT
41+
sin(-d1); // COMPLIANT
42+
cos(-d1); // COMPLIANT
43+
tan(-d1); // COMPLIANT
44+
}
45+
46+
if (x < 30) {
47+
f1 = 3.14 * 100;
48+
d1 = 3.14 * 100;
49+
sin(f1); // NON-COMPLIANT
50+
cos(f1); // NON-COMPLIANT
51+
tan(f1); // NON-COMPLIANT
52+
sin(d1); // NON-COMPLIANT
53+
cos(d1); // NON-COMPLIANT
54+
tan(d1); // NON-COMPLIANT
55+
sin(-f1); // NON-COMPLIANT
56+
cos(-f1); // NON-COMPLIANT
57+
tan(-f1); // NON-COMPLIANT
58+
sin(-d1); // NON-COMPLIANT
59+
cos(-d1); // NON-COMPLIANT
60+
tan(-d1); // NON-COMPLIANT
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `DIR-4-11` - `LowPrecisionPeriodicTrigonometricFunctionCall.ql`:
2+
- New query within rule added to detect calls to periodic trigonometric functions with values outside of pi*k for k that depends on implementation and application precision goals, assuming k=1 for 32 bit floating types and k=10 for 64 bit floating types.

Diff for: cpp/common/src/codingstandards/cpp/exclusions/c/Contracts.qll

+17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import codingstandards.cpp.exclusions.RuleMetadata
66
newtype ContractsQuery =
77
TDoNotViolateInLineLinkageConstraintsQuery() or
88
TCheckMathLibraryFunctionParametersQuery() or
9+
TLowPrecisionPeriodicTrigonometricFunctionCallQuery() or
910
TFunctionErrorInformationUntestedQuery()
1011

1112
predicate isContractsQueryMetadata(Query query, string queryId, string ruleId, string category) {
@@ -27,6 +28,15 @@ predicate isContractsQueryMetadata(Query query, string queryId, string ruleId, s
2728
ruleId = "DIR-4-11" and
2829
category = "required"
2930
or
31+
query =
32+
// `Query` instance for the `lowPrecisionPeriodicTrigonometricFunctionCall` query
33+
ContractsPackage::lowPrecisionPeriodicTrigonometricFunctionCallQuery() and
34+
queryId =
35+
// `@id` for the `lowPrecisionPeriodicTrigonometricFunctionCall` query
36+
"c/misra/low-precision-periodic-trigonometric-function-call" and
37+
ruleId = "DIR-4-11" and
38+
category = "required"
39+
or
3040
query =
3141
// `Query` instance for the `functionErrorInformationUntested` query
3242
ContractsPackage::functionErrorInformationUntestedQuery() and
@@ -52,6 +62,13 @@ module ContractsPackage {
5262
TQueryC(TContractsPackageQuery(TCheckMathLibraryFunctionParametersQuery()))
5363
}
5464

65+
Query lowPrecisionPeriodicTrigonometricFunctionCallQuery() {
66+
//autogenerate `Query` type
67+
result =
68+
// `Query` type for `lowPrecisionPeriodicTrigonometricFunctionCall` query
69+
TQueryC(TContractsPackageQuery(TLowPrecisionPeriodicTrigonometricFunctionCallQuery()))
70+
}
71+
5572
Query functionErrorInformationUntestedQuery() {
5673
//autogenerate `Query` type
5774
result =

Diff for: rule_packages/c/Contracts.json

+13
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@
4444
"implementation_scope": {
4545
"description": "This query identifies possible domain, pole and range errors on a selection of C standard library fuctions from math.h."
4646
}
47+
},
48+
{
49+
"description": "Trigonometric periodic functions have significantly less precision when called with large floating-point values.",
50+
"kind": "problem",
51+
"name": "The validity of values passed to trigonometric functions shall be checked",
52+
"precision": "high",
53+
"severity": "warning",
54+
"short_name": "LowPrecisionPeriodicTrigonometricFunctionCall",
55+
"tags": [
56+
"correctness",
57+
"external/misra/c/2012/third-edition-first-revision",
58+
"external/misra/c/2012/amendment3"
59+
]
4760
}
4861
],
4962
"title": "The validity of values passed to library functions shall be checked"

0 commit comments

Comments
 (0)