JPCERT コーディネーションセンター

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 へのポインタ型ではなく、単純なポインタ型として定義されている(例えば LPPOINTLPSIZE など)。このような場合には、元の構造体型から独自に型定義をして使うとよいだろう。

#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

自動検出

ツール

バージョン

チェッカー

説明

CodeSonar 4.2 LANG.STRUCT.PIT Pointer type inside typedef

Compass/ROSE

 

 

 

LDRA tool suite

9.5.6

299 S

一部実装済み

Parasoft C/C++test 9.5 MISRA2004-16_7_b Fully implemented
PRQA QA-C 8.2 Secondary analysis 実装済み
関連するガイドライン
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 82)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter