LoginSignup
3

C Secure Coding Rules(2) 5.2. Accessing freed memory

Last updated at Posted at 2018-04-02

ISO/IEC TS 17961:2013
Information Technology — Programming languages, their environments and system software interfaces — C Secure Coding Rules
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1624.pdf

この文書は、ISO/IEC JTC1 SC22 WG14の作業文書(Working Draft)です。
公式のISO/IEC TS 17961:2013原本ではありません。

技術内容を検討し、ISO/IEC JTC1 SC22 WG14にフィードバックするために用いるものです。

ISO/IEC TS 17961:2013 C Secure Coding Rules(1)一覧

ISO/IEC TS 17961:2013 C Secure Coding Rules(1) All list(to be confirmed) - kaizen_nagoya @ Qiita
https://qiita.com/kaizen_nagoya/items/54e056195c4f11b850a1

一つの規則で複数回のコンパイルが必要な場合、別記事にしています。

作業予定

規則の例(断片等)をコンパイル、実行する予定です。
1: コンパイルエラーが出ないようにする。
 一覧のaccfree.cがこの段階です。
2: 実行時エラーが出ないようにする。
 一覧のptrcomp.cがこの段階です。
3: 意味のある出力が出るようにする。
 検討中。

現状では、変な代入、奇異な操作が頻出します。
コンパイルエラーが出ないようにするなるべく短い記述で済まそうという趣旨で、他意はありません。
よりよい記述に変更する予定です。

利用コンパイラ

Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.4.0
または
clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-apple-darwin17.4.0

gcc-7 (Homebrew GCC 7.3.0_1) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.

環境(Environment)

hosted Environment macOS 10.13.3 or 10.12.9

コンパイル用shell script

C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da

5.2. Accessing freed memory[accfree]

EXAMPLE 1 In this noncompliant example, a diagnostic is required because head->next is accessed after head has been freed.

sample.c
struct List { struct List *next; /* ... */ };
void free_list(struct List *head) {
  for (; head != NULL; head = head->next) { // diagnostic required
  free(head);
  }
}

上記を含むコンパイル可能そうなコードに追記。

accfree-old.c
// ISO/IEC JTC 1/SC 22/WG 14 N 1624 Date: 2012-06-26 ISO/IEC TS 17961, p.7
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1624.pdf
/// lines are added by Dr. Kiyoshi Ogawa, 2018
/// Compiled on 
///  Clang(LLVM) clang version 6.0.0 (tags/RELEASE_600/final) 
///  GCC(GNU) gcc-7 (Homebrew GCC 7.3.0_1) 7.3.0
/// hosted Environment macOS 10.13.3 or 10.12.9
// EXAMPLE 1 In this noncompliant example, a diagnostic is required because head->next is accessed after head has been freed.

#include <stdio.h>/// for printf
#include <stdlib.h>/// for EXIT_SUCCESS

struct List { struct List *next; /* ... */ };
void free_list(struct List *head) {
  for (; head != NULL; head = head->next) { // diagnostic required
  printf("%ld %ld \n",(long)head, (long)head->next);
  free(head);
  }
}
int main(int argc, char** argv){///
  struct List *lista;///
  size_t sz = sizeof(List);///
  lista = malloc(sz);///
  lista->next = NULL;///
  printf("mp:%s \n",mp);///
  free_list(&lista);///
  return EXIT_SUCCESS;///
}///
$ cc accfree.c
$ ./a.out
a.out(66907,0x7fffa098d340) malloc: *** error for object 0x7ffee1996748: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

$ ./gcc7ts.sh accfree
$ clang accfree.c
140732745819992 0 
accfreel(87181,0x7fffa098d340) malloc: *** error for object 0x7ffee552a758: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
./gcc7ts.sh: line 4: 87181 Abort trap: 6           ./$1l $2

$ gcc-7 accfree.c
140732796196712 4478755282 
accfreeg(87190,0x7fffa098d340) malloc: *** error for object 0x7ffee8535768: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
./gcc7ts.sh: line 8: 87190 Abort trap: 6           ./$1g $2

mallocを付け加えて実行エラーが出ないようにした。

accfree.c
// ISO/IEC JTC 1/SC 22/WG 14 N 1624 Date: 2012-06-26 ISO/IEC TS 17961, p.7
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1624.pdf
/// lines are added by Dr. Kiyoshi Ogawa, 2018
/// Compiled on Clang(LLVM) and GCC(GNU)
// EXAMPLE 1 In this noncompliant example, a diagnostic is required because head->next is accessed after head has been freed.

#include <stdio.h>/// for printf
#include <stdlib.h>/// for EXIT_SUCCESS

struct List { struct List *next; /* ... */ };
void free_list(struct List *head) {
  for (; head != NULL; head = head->next) { // diagnostic required
  printf("%ld %ld \n",(long)head, (long)head->next);
  free(head);
  }
}
int main(int argc, char** argv){///
  struct List *lista;///
  size_t sz = sizeof(struct List);///
  lista = malloc(sz);///
  lista->next = NULL;///
  printf("%ld \n",(long)lista);///
  free_list(lista);///
  return EXIT_SUCCESS;///
}///
shell
$ cc accfree.c
$ ./a.out
140499558073152 
140499558073152 0 

$./gcc7ts.sh accfree
$ clang accfree.c
140206166508352 
140206166508352 0 

$ gcc-7 accfree.c
140691146539008 
140691146539008 0 

EXAMPLE 2 In this noncompliant example, a diagnostic is required because buf is written to after it has been freed.

accfree2.c
// ISO/IEC JTC 1/SC 22/WG 14 N 1624 Date: 2012-06-26 ISO/IEC TS 17961, p.8
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1624.pdf
/// lines are added by Dr. Kiyoshi Ogawa, 2018
/// Compiled on 
///  Clang(LLVM) clang version 6.0.0 (tags/RELEASE_600/final) 
///  GCC(GNU) gcc-7 (Homebrew GCC 7.3.0_1) 7.3.0
/// hosted Environment macOS 10.13.3 or 10.12.9
// EXAMPLE 2 In this noncompliant example, a diagnostic is required because buf is written to after it has been freed.

#include <stdio.h> // for printf
#include <stdlib.h> // for EXIT_SUCCESS
#include <string.h> // for strlen

int main(int argc, char *argv[]) {///
  if (argc < 2) {
    printf("argc:%d\n",argc);
    /* ... */
    return EXIT_FAILURE;
  }
  char *return_val = 0;
  const size_t bufsize = strlen(argv[1]) + 1;
  char *buf = (char *)malloc(bufsize);
  if (!buf) {
    /* ... */
    printf("!buf\n");
    return EXIT_FAILURE;
  }
  /* ... */
  printf("buf:%d\n",(int)buf);
  free(buf);
  /* ... */
  return_val = strncpy(buf, argv[1], bufsize); // diagnostic required
  if (return_val) {
    printf("*return_val:%d\n",(int)*return_val);
    /* ... */
  }
  return EXIT_SUCCESS;
}
shell
./gcc7ts.sh accfree2
$ clang accfree2.c
argc:1

$ gcc-7 accfree2.c
argc:1
OgawaKiyoshi-no-MacBook-Pro:ts17961 ogawakiyoshi$ ./gcc7ts.sh accfree2 newarg
$ clang accfree2.c
buf:140704637517824
*return_val:110

$ gcc-7 accfree2.c
buf:140598275212096
*return_val:110

このプログラムは最終形です。起動パラメータなし、起動パラメータありの2種類で実行しています。

EXAMPLE 3 In this noncompliant example, a diagnostic is required because realloc may free c_str1 when it returns NULL, resulting in c_str1 being freed twice.

accfree3-old.c
// ISO/IEC JTC 1/SC 22/WG 14 N 1624 Date: 2012-06-26 ISO/IEC TS 17961, p.8
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1624.pdf
/// lines are added by Dr. Kiyoshi Ogawa, 2018
/// Compiled on 
///  Clang(LLVM) clang version 6.0.0 (tags/RELEASE_600/final) 
///  GCC(GNU) gcc-7 (Homebrew GCC 7.3.0_1) 7.3.0
/// hosted Environment macOS 10.13.3 or 10.12.9
// EXAMPLE 3 In this noncompliant example, a diagnostic is required because realloc may free c_str1 when it returns NULL, resulting in c_str1 being freed twice.

#include <stdio.h> // for printf
#include <stdlib.h> // for EXIT_SUCCESS
#include <string.h> // for strlen

void f(char * c_str1, size_t size) {
  char * c_str2 = (char *)realloc(c_str1, size);
  if (c_str2 == NULL) {
    free(c_str1); // diagnostic required
  return;
  }
  printf("end of f\n");// added for output
}
int main(int argc, char** argv){// added by O.K.
  f(argv[0], sizeof(argv[0]);// added by O.K.
  return EXIT_SUCCESS;// added by O.K.
}// added by O.K.
$ cc accfree3.c
$ ./a.out
a.out(67486,0x7fffa098d340) malloc: *** error for object 0x7ffee823e8c8: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

$ ./gcc7ts.sh accfree3
clang accfree3.c
accfree3l(84939,0x7fffa098d340) malloc: *** error for object 0x7ffeee5798d8: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
./gcc7ts.sh: line 4: 84939 Abort trap: 6           ./$1l $2
gcc-7 accfree3.c
accfree3g(84948,0x7fffa098d340) malloc: *** error for object 0x7ffee32b68d8: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
./gcc7ts.sh: line 7: 84948 Abort trap: 6           ./$1g $2
accfree3.c
// ISO/IEC JTC 1/SC 22/WG 14 N 1624 Date: 2012-06-26 ISO/IEC TS 17961, p.8
// http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1624.pdf
/// lines are added by Dr. Kiyoshi Ogawa, 2018
/// Compiled on Clang(LLVM) and GCC(GNU)
// EXAMPLE 3 In this noncompliant example, a diagnostic is required because realloc may free c_str1 when it returns NULL, resulting in c_str1 being freed twice.

#include <stdio.h> /// for printf
#include <stdlib.h> /// for EXIT_SUCCESS
#include <string.h> /// for strlen

void f(char * c_str1, size_t size) {
  printf("%s start of f()\n",c_str1);///
  char * c_str2 = (char *)realloc(c_str1, size);
  if (c_str2 == NULL) {
    printf("NULL");
    free(c_str1); // diagnostic required
    return;
  }
  printf("%s end of f()\n",c_str1);///
}
int main(int argc, char** argv){///
  size_t sz = sizeof(argv[0]);///
  char * mp = malloc(sz);///
  memcpy(mp,argv[0],sz);///
  printf("mp:%s \n",mp);///
  f(mp, sz);///
  return EXIT_SUCCESS;///
}///
 ./gcc7ts.sh accfree3 new
$ clang accfree3.c
mp:./accfre 
./accfre start of f()
./accfre end of f()

$ gcc-7 accfree3.c
mp:./accfre 
./accfre start of f()
./accfre end of f()

#参考文献
コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da

C言語(C++)に対する誤解、曲解、無理解、爽快。
https://qiita.com/kaizen_nagoya/items/3f3992c9722c1cee2e3a

MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9

どうやって MISRA C Example Suiteをコンパイルするか
https://qiita.com/kaizen_nagoya/items/fbdbff5ff696e2ca7f00

[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de

文書履歴

ver. 0.10 初稿 20180403
ver. 0.11 gcc-7追記 20180407
ver. 0.12 Example節項目追記、修正前後記録 20180407
ver. 0.13 ありがとう追記 20230413

最後までおよみいただきありがとうございました。

いいね 💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚 and follow me for your happy life.

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3