Create rule S7116: The first element of an array should not be accessed implicitly CPP-5674
This commit is contained in:
parent
65c443e810
commit
b2e18a89be
24
rules/S7116/cfamily/metadata.json
Normal file
24
rules/S7116/cfamily/metadata.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"title": "The first element of an array should not be accessed implicitly",
|
||||
"type": "CODE_SMELL",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "5min"
|
||||
},
|
||||
"tags": [
|
||||
"confusing"
|
||||
],
|
||||
"defaultSeverity": "Minor",
|
||||
"ruleSpecification": "RSPEC-7116",
|
||||
"sqKey": "S7116",
|
||||
"scope": "All",
|
||||
"defaultQualityProfiles": ["Sonar way"],
|
||||
"quickfix": "covered",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"MAINTAINABILITY": "LOW"
|
||||
},
|
||||
"attribute": "CLEAR"
|
||||
}
|
||||
}
|
152
rules/S7116/cfamily/rule.adoc
Normal file
152
rules/S7116/cfamily/rule.adoc
Normal file
@ -0,0 +1,152 @@
|
||||
The first element of an array should be accessed using the subscript operator (`array[0]`),
|
||||
instead of dereferencing the array (``++*array++``) or using the arrow operator on it (``++array->mem++``).
|
||||
|
||||
== Why is this an issue?
|
||||
|
||||
When an expression refers to an object of array type,
|
||||
it can produce a pointer to the first element of the array.
|
||||
This behavior is known as array-to-pointer decay or simply array decay.
|
||||
|
||||
Because of array-to-pointer decay, it is possible to use the dereference operator (`*`) or
|
||||
the pointer member access operator (``++->++``) on an array object to access its first element.
|
||||
However, it remains unclear if accessing the first element was intentional.
|
||||
In contrast, using array subscript (`[0]`) removes any such ambiguity.
|
||||
|
||||
This rule raises an issue when the deference operator or the member access operator is used
|
||||
on an array.
|
||||
|
||||
[source,c]
|
||||
----
|
||||
struct Struct { int x; };
|
||||
Struct elems[10];
|
||||
int integers[5];
|
||||
|
||||
void init() {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
*integers = i; // Noncompliant: "*" used to access "integers[0]"
|
||||
}
|
||||
}
|
||||
|
||||
void process() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
elems->x *= 2; // Noncompliant: "->" used to access "elems[0]"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
== How to fix it
|
||||
|
||||
The fix depends on the intended effect of the code:
|
||||
|
||||
* If the intent is to access the first element, ``++->++`` or `*` should be replaced with an explicit subscripts with `[0]`;
|
||||
* If another element was meant to be accessed, a subscript with the appropriate index should be used;
|
||||
* If the intent was to dereference a pointer (for instance to iterate on array elements), the array should be replaced with the appropriate pointer.
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,c,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
struct Struct { int x; };
|
||||
Struct elems[10];
|
||||
|
||||
void process() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
elems->x *= 2; // Noncompliant: "->" used to access "elems[0]"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
If the access to the first element was intentional, you can use subscript explicitly:
|
||||
[source,cpp,,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
struct Struct { int x; };
|
||||
Struct elems[10];
|
||||
|
||||
void process() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
elems[0].x *= 2; // Compliant: element accessed through subscript
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Otherwise, if ``++i++``th element was to be updated:
|
||||
[source,cpp]
|
||||
----
|
||||
struct Struct { int x; };
|
||||
Struct elems[10];
|
||||
|
||||
void process() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
elems[i].x *= 2; // Compliant: element accessed through subscript
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Finally, the ``++i++``th element can be accessed using ``++->++`` and `elem` pointer:
|
||||
[source,cpp]
|
||||
----
|
||||
struct Struct { int x; };
|
||||
Struct elems[10];
|
||||
|
||||
void process() {
|
||||
for (Struct* elem = elems, end = elems + 10; elem != end; ++elem) {
|
||||
elem->x *= 2; // Compliant: dereferencing a pointer
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,cpp,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
int integers[5];
|
||||
|
||||
void init() {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
*integers = i; // Noncompliant: "*" used to access "integers[0]"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
The intent was probably to access the ``++i++``th element of `integers`:
|
||||
|
||||
[source,cpp,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
int integers[5];
|
||||
|
||||
void init() {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
integers[i] = i; // Compliant: element accessed through subscript
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Or, to preserve current behavior, use a subscript to explicitly access the first element:
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
int integers[5];
|
||||
|
||||
void init() {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
integers[0] = i; // Compliant: element accessed through subscript
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* {cpp} reference - https://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay[Array-to-pointer decay]
|
||||
|
||||
=== Related rules
|
||||
|
||||
* S945 detects array decays that happen when passing an array object to a function that has a pointer parameter.
|
2
rules/S7116/metadata.json
Normal file
2
rules/S7116/metadata.json
Normal file
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user