DCL05-C. typedef による型定義ではポインタ型を避ける
型定義(typedef
)を活用することで、コードを読みやすくすることができる。しかし、型定義によりポインタ型を導入する場合、const
-correct なコードを書くためには注意が必要だ。なぜなら、const
修飾子がポインタ型に対して適用されるということを正しく理解することが難しいからだ。
違反コード
次のコード例では、型定義を行うことによりコードの可読性が向上しているが、const
-correct なコードではなくなってしまっている。const
修飾子は typedef
された型自体に適用されるものであり、元のオブジェクト型に適用されるものではない。したがって関数 func
の引数は、const struct obj
へのポインタではなく、struct obj
への const
ポインタである。
struct obj { int i; float f; }; typedef struct obj *ObjectPtr; void func(const ObjectPtr o) { /* 期待に反して o の中身は変更可能 */ }
適合コード
以下の適合コードにおける型定義ではポインタ型でない型を定義しており、const
-correct なコードになっている。
struct obj { int i; float f; }; typedef struct obj Object; void func(const Object *o) { /* o の中身は変更できない */ }
違反コード (Windows)
Win32 SDK では Win32 API に含まれるほとんどの型について型定義が行われているが、const
-correct に関するバグが存在した。
#include <Windows.h> /* typedef char *LPSTR; */ void func(const LPSTR str) { /* 期待に反して str の中身は変更可能 */ }
適合コード (Windows)
次の適合コードでは、Win32 API で広く使用されている命名規則にしたがい、const
型が正しく使用されている。
#include <Windows.h> /* typedef const char *LPCSTR; */ void func(LPCSTR str) { /* str の中身は変更できない */ }
違反コード (Windows)
Win32 API で扱われる多くの構造体データは const
へのポインタ型ではなく、単純なポインタ型として定義されている(例えば LPPOINT
や LPSIZE
など)。このような場合には、元の構造体型から独自に型定義をして使うとよいだろう。
#include <Windows.h> /* typedef struct tagPOINT { long x, y; } POINT, *LPPOINT; */ void func(const LPPOINT pt) { /* 期待に反して pt の中身は変更可能 */ }
適合コード (Windows)
#include <Windows.h> /* typedef struct tagPOINT { long x, y; } POINT, *LPPOINT; */ typedef const POINT *LPCPOINT; void func(LPCPOINT pt) { /* pt の中身は変更できない */ }
違反コード
次の違反コードでは、関数 signal()
の宣言は読みづらく理解しにくい。
void (*signal(int, void (*)(int)))(int);
適合コード
以下の適合コードでは、typedef
を使って違反コードと同じ関数型を定義している。
typedef void SighandlerType(int signum); extern SighandlerType *signal( int signum, SighandlerType *handler );
例外
関数ポインタ型については、このガイドラインは適用されない。
リスク評価
コードの読みやすさは、脆弱性を発見し排除する上で重要である。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
DCL05-C |
低 |
低 |
中 |
P2 |
L3 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Astrée |
20.10
|
pointer-typedef | Fully checked |
Axivion Bauhaus Suite |
6.9.0 |
CertC-DCL05 |
|
CodeSonar |
6.0p0
|
LANG.STRUCT.PIT | Pointer type inside typedef |
Compass/ROSE |
|
|
|
LDRA tool suite |
9.7.1
|
299 S |
一部実装済み |
Parasoft C/C++test |
2020.2
|
CERT_C-DCL05-a |
Declare a type of parameter as typedef to pointer to const if the pointer is not used to modify the addressed object |
PRQA QA-C |
9.7
|
5004 | 実装済み |
RuleChecker |
20.10
|
pointer-typedef |
Fully checked |
関連するガイドライン
CERT C コーディングスタンダード | DCL12-C. 抽象データ型は opaque な型を使って実装する |
SEI CERT C++ Coding Standard | DCL05-CPP. Use typedefs to improve code readability |
翻訳元
これは以下のページを翻訳したものです。
DCL05-C. Use typedefs of non-pointer types only (revision 92)