メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C: Rule POS30-C

Use the readlink() function properly

説明

ルール定義

関数 readlink() を適切に使用します。1

Polyspace 実装

ルール チェッカーは、"readlink() の不適切な使用" をチェックします。

すべて展開する

問題

readlink() の不適切な使用は、readlink() のバッファー サイズの引数に、バッファー内に NULL 終端用の領域を残さない値を渡す場合に発生します。

次に例を示します。

size_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
この 3 番目の引数のサイズは 2 番目の引数のサイズとまったく同じです。シンボリック リンクがバッファーを占有する場合、このように readlink() を使用すると、NULL 終端を入れる領域が残りません。

リスク

関数 readlink() は、シンボリック リンク (最初の引数) のコンテンツをバッファー (2 番目の引数) にコピーします。ただし、この関数はコピーしたコンテンツに NULL 終端を追加しません。readlink() を使用後、NULL 終端をバッファーに明示的に追加しなければなりません。

readlink の使用時にバッファー全体が占有されると、NULL 終端の領域が残りません。

修正方法

関数 readlink() を使用するときは、3 番目の引数をバッファー サイズよりも 1 文字分短くします。

その後、NULL 終端をバッファーに追加します。NULL 終端の追加場所を決めるには、readlink() の戻り値をチェックします。戻り値が -1 の場合、エラーが発生しています。そうでない場合、戻り値はコピーされた文字数 (バイト) です。

例 - readlink の不適切なサイズの引数
#include <unistd.h>

#define SIZE1024 1024

extern void display_path(const char *);

void func() {
    char buf[SIZE1024];
    ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf)); //Noncompliant
    if (len > 0) {
        buf[len - 1] = '\0';
    }
    display_path(buf);
}

この例では、readlink の 3 番目の引数がバッファー (2 番目の引数) のサイズとまったく同じです。最初の引数がバッファーを占有する場合、このように readlink を使用すると、NULL 終端の領域が残りません。

また、文字がコピーされないとき、readlink の戻り値は 0 です。以下のステートメントでは、len が 0 のときにバッファー アンダーフローになります。

buf[len - 1] = '\0';

修正 — サイズの引数をバッファー サイズよりも 1 文字分短くする

1 つの修正方法として、readlink の 3 番目の引数を 2 番目の引数のサイズよりも 1 文字分短くします。

修正した次のコードでは、readlink が 0 を返す場合も考慮します。

#include <stdlib.h>
#include <unistd.h>

#define fatal_error() abort()
#define SIZE1024 1024

extern void display_path(const char *);

void func() {
    char buf[SIZE1024];
    ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf) - 1); 
    if (len != -1) {
        buf[len] = '\0';
        display_path(buf);
    }
    else {
        /* Handle error */
        fatal_error();
    }
}

チェック情報

グループ: Rule 50.POSIX (POS)

バージョン履歴

R2019a で導入

すべて展開する


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.