Finding Bugs with PC-lint A Static Analysis Tool for C/C++

Slides:



Advertisements
Similar presentations
C Language.
Advertisements

What is a pointer? First of all, it is a variable, just like other variables you studied So it has type, storage etc. Difference: it can only store the.
This Time Pointers (declaration and operations) Passing Pointers to Functions Const Pointers Bubble Sort Using Pass-by-Reference Pointer Arithmetic Arrays.
Kernighan/Ritchie: Kelley/Pohl:
Pointers Typedef Pointer Arithmetic Pointers and Arrays.
Source Code Analysis Tools Philippe CHARMAN Last update:
Informática II Prof. Dr. Gustavo Patiño MJ
6/10/2015C++ for Java Programmers1 Pointers and References Timothy Budd.
 2006 Pearson Education, Inc. All rights reserved Midterm review Introduction to Classes and Objects.
Chapter 8. 2 Objectives You should be able to describe: One-Dimensional Arrays Array Initialization Arrays as Arguments Two-Dimensional Arrays Common.
1 Data Structures Data Structures Topic #2. 2 Today’s Agenda Data Abstraction –Given what we talked about last time, we need to step through an example.
1 Pointers, Dynamic Data, and Reference Types Review on Pointers Reference Variables Dynamic Memory Allocation –The new operator –The delete operator –Dynamic.
Chapter 2: Introduction to C++.
1 The first step in understanding pointers is visualizing what they represent at the machine level. In most modern computers, main memory is divided into.
Chapter 8 Arrays and Strings
1 Procedural Concept The main program coordinates calls to procedures and hands over appropriate data as parameters.
Review of C++ Programming Part II Sheng-Fang Huang.
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
Pointer Data Type and Pointer Variables
Chapter 6 Vectors and arrays: Arrays: Run the following code. Anything unusual? #include using namespace std; #define N 10 #define M 11 int main() { int.
Pointers CS362. Pointers A Pointer is a variable that can hold a memory address Pointers can be used to: Indirectly reference existing variables (sometimes.
C Programming Tutorial – Part I CS Introduction to Operating Systems.
Chapter 8 Arrays and Strings
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look, Part 2.
SEN 909 OO Programming in C++ Final Exam Multiple choice, True/False and some minimal programming will be required.
C++ Programming: From Problem Analysis to Program Design, Fifth Edition Arrays.
Learners Support Publications Classes and Objects.
Fundamental Programming: Fundamental Programming Introduction to C++
Chapter 8: Arrays and Functions Department of Computer Science Foundation Year Program Umm Alqura University, Makkah Computer Programming Skills
Data TypestMyn1 Data Types The type of a variable is not set by the programmer; rather, it is decided at runtime by PHP depending on the context in which.
1 Pointers to structs. 2 A pointer to a struct is used in the same way as a pointer to a simple type, such as an int. Pointers to structs were introduced.
COMPUTER PROGRAMMING. Functions’ review What is a function? A function is a group of statements that is executed when it is called from some point of.
Object Oriented Programming Elhanan Borenstein Lecture #3 copyrights © Elhanan Borenstein.
C++ Classes and Data Structures Jeffrey S. Childs
Introducing C++ Programming Lecture 3 Dr. Hebbat Allah A. Elwishy Computer & IS Assistant Professor
Topic 3: C Basics CSE 30: Computer Organization and Systems Programming Winter 2011 Prof. Ryan Kastner Dept. of Computer Science and Engineering University.
A First Book of C++: From Here To There, Third Edition2 Objectives You should be able to describe: One-Dimensional Arrays Array Initialization Arrays.
Structured Programming Approach Module VIII - Additional C Data Types Structures Prof: Muhammed Salman Shamsi.
 2003 Prentice Hall, Inc. All rights reserved. 1 IS 0020 Program Design and Software Tools Preprocessor Midterm Review Lecture 7 Feb 17, 2004.
More Array Access Examples Here is an example showing array access logic: const int MAXSTUDENTS = 100; int Test[MAXSTUDENTS]; int numStudents = 0;... //
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
POINTERS. // Chapter 3 - Program 1 - POINTERS.CPP #include int main() { int *pt_int; float *pt_float; int pig = 7, dog = 27; float x = , y = 32.14;
1 Becoming More Effective with C++ … Day Two Stanley B. Lippman
C++ for Java Programmers Chapter 2. Fundamental Daty Types Timothy Budd.
1 Mr. Muhammad Hanif Lecturer Information Technology MBBS Campus Dadu University of SIndh.
EEL 3801 C++ as an Enhancement of C. EEL 3801 – Lotzi Bölöni Comments  Can be done with // at the start of the commented line.  The end-of-line terminates.
CSC 221: Computer Programming I Fall 2001  arrays  homogeneous collection of items, accessible via an index  initializing/traversing/displaying arrays.
Chapter 1 C++ Basics Review (Section 1.4). Classes Defines the organization of a data user-defined type. Members can be  Data  Functions/Methods Information.
Struct s (7.4) Used as data aggregates for an entity can be different types of data e.g. for student id, name, GPA, address,... Similar to classes, but.
Extra Recitations Wednesday 19:40-22:30 FENS L055 (tomorrow!) Friday 13:40-16:30 FENS L063 Friday 17: :30 FENS L045 Friday 19:40-22:30 FENS G032.
Array Size Arrays use static allocation of space. That is, when the array is created, we must specify the size of the array, e.g., int[] grades = new int[100];
1 Recall that... char str [ 8 ]; str is the base address of the array. We say str is a pointer because its value is an address. It is a pointer constant.
1 Chapter 15-1 Pointers, Dynamic Data, and Reference Types Dale/Weems.
Dr. Yang, QingXiong (with slides borrowed from Dr. Yuen, Joe) LT:10 Advance Pointer Array, String and Dynamic Memory Allocation CS2311 Computer Programming.
2. C FUNDAMENTALS. Example: Printing a Message /* Illustrates comments, strings, and the printf function */ #include int main(void) { printf("To C, or.
SEQUENTIAL AND OBJECT ORIENTED PROGRAMMING Arrays.
Announcements Assignment 2 Out Today Quiz today - so I need to shut up at 4:25 1.
Dynamic Memory Management & Static Class Members Lecture No 7 Object Oriented Programming COMSATS Institute of Information Technology.
Windows Programming Lecture 06. Data Types Classification Data types are classified in two categories that is, – those data types which stores decimal.
Windows Programming Lecture 03. Pointers and Arrays.
You learned how to declare pointer variables how to store the address of a variable into a pointer variable of the same type as the variable how to manipulate.
C++ Lesson 1.
C Programming Tutorial – Part I
C Basics.
Memberwise Assignment / Initialization
Chapter 15 Pointers, Dynamic Data, and Reference Types
Chapter 15 Pointers, Dynamic Data, and Reference Types
Classes and Objects.
Chapter 2: Introduction to C++.
Presentation transcript:

Finding Bugs with PC-lint A Static Analysis Tool for C/C++ Durée: 1h Ajouter sol exercices, explanation Philippe CHARMAN charman@fr.ibm.com http://users.polytech.unice.fr/~charman/ Last update: 05-15-2014

PC-lint & FlexeLint Check the source code of C/C++ and detect any potential issue: bug, inconsistency, non-portable code, suspicious code, etc. The analyse is performed on all files Pseudo-execution of the code Available on Windows (PC-lint) and Unix (FlexeLint) License: About 500$, no trial license 

PC-lint & FlexeLint An interactive demo is available here: http://www.gimpel-online.com/OnlineTesting.html by clicking on Do-It-Yourself Example (C++)

PC-lint & FlexeLint For each of the following 10 examples: Without compiling the code, try to find the bug If you haven’t found the bug, compile the code and look if the compiler reports a warning If you still haven’t found the bug, copy-paste the code in the PC-lint demo window and click on the button « Analyse Code » to see the messages reported by PC-lint. Fix the code, compile it and check the execution results and check the fix in the window demo

Example 1 #include <stdio.h> int main() { int i; int a[] = {1,2,3}; int n = sizeof(a)/sizeof(int); for (i=0;i<=n;i++) printf("a[%d]=%d\n",i,a[i]); return 0; }

Analysing example 1 1  #include <stdio.h> 2   3  int main() 4  {  5    int i;  6    int a[] = {1,2,3};  7    int n = sizeof(a)/sizeof(int); 8    for (i=0;i<=n;i++)                                        _ 9      printf("a[%d]=%d\n",i,a[i]);  diy.cpp  9  Warning 661:  Possible access of out-of-bounds pointer (1 beyond end of data) by operator '[' [Reference: file diy.cpp: lines 7, 8, 9] 10    return 0; 11  } 12  

Explanation of warning 661 661 possible access of out-of-bounds pointer ('Integer' beyond end of data) by operator 'String' An out-of-bounds pointer may have been accessed. See message 415 for a description of the parameters Integer and String. For example: int a[10]; if( n <= 10 ) a[n] = 0; Here the programmer presumably should have written n<10. This message is similar to messages 415 and 796 but differs from them by the degree of probability.

Example 2 #include <string.h> class X { int *p; public: X() { p = new int[20]; } void init() { memset( p, 20, 'a' ); } ~X() { delete p; } };

Analysing example 2 1  #include <string.h> 2   3  class X { 4      int *p; 5    public: 6      X() 7          { p = new int[20]; } 8      void init() 9          { memset( p, 20, 'a'  ); } 10      ~X() 11          { delete p; }                       _ 7          { p = new int[20]; } diy.cpp  7  Info 1732:  new in constructor for class 'X' which has no assignment operator diy.cpp  7  Info 1733:  new in constructor for class 'X' which has no copy constructor                                        _ 9          { memset( p, 20, 'a'  ); } diy.cpp  9  Warning 669:  Possible data overrun for function 'memset(void *, int, unsigned int)', argument 3 (size=97) exceeds argument 1 (size=80) [Reference: file diy.cpp: lines 7, 9]                           _ 11          { delete p; } diy.cpp  11  Warning 424:  Inappropriate deallocation (delete) for 'new[]' data 12      };

Explanation of warning 669 669 Possible data overrun for function 'Symbol', argument Integer exceeds argument Integer Reference This message is for data transfer functions such as memcpy, strcpy, fgets, etc. when the size indicated by the first cited argument (or arguments) can possibly exceed the size of the buffer area cited by the second. The message may also be issued for user functions via the -function option See Function Mimicry and Value Tracking.

Example 3 #include <stdio.h> int quotient(int *q, int *p) { if(*p) return *q/*p /* compute ratio */ ; else return *q; } int main() { int n = 20, m = 4; int q = quotient( &n, &m ); printf( "%d/%d = %d\n", n, m, q ); // displays 20 instead of 5 return 0;

Analysing example 3 1  #include <stdio.h> 2   3  int quotient(int *q, int *p) {                                  _ 4    if(*p) return *q/*p  /* compute ratio */ ; diy.cpp  4  Warning 602:  Comment within comment 5    else return *q;         _ 6  } diy.cpp  6  Info 818:  Pointer parameter 'p' (line 3) could be declared as pointing to const diy.cpp  6  Info 818:  Pointer parameter 'q' (line 3) could be declared as pointing to const 7   8  int main() { 9    int n = 20, m = 4; 10    int q = quotient( &n, &m ); 11    printf( "%d/%d = %d\n", n, m, q ); 12    return 0; 13  }

Explanation of warning 602 02 Comment within comment The sequence /* was found within a comment. Was this deliberate? Or was a comment end inadvertently omitted? If you want PC-lint/FlexeLint to recognize nested comments you should set the Nested Comment flag using the +fnc option. Then this warning will not be issued. If it is your practice to use the sequence: /* /* */ then use -e602.

Example 4 #include <stdio.h> #include <stdlib.h> const char *flowers[] = { "rose", "tulip", "daisy" "petunia", "orchid", "lily" }; int main() { int i; int choice; for( i = 0; i < 25; i++ ) { choice = rand() % 6; printf( "%s\n", flowers[choice] ); } return 0;

Analysing example 4 1  #include <stdio.h>      2  #include <stdlib.h>      3        4  const char *flowers[] =  {      5      "rose", "tulip", "daisy"             _      6      "petunia", "orchid", "lily" diy.cpp  6  Info 786:  String concatenation within initializer      7    };      8        9  int main() {     10    int i;     11    int choice;     12         13    for( i = 0; i < 25; i++ ) {     14        choice = rand() % 6;     15        printf( "%s\n", flowers[choice] );     16      }     17    return 0;     18  }

Explanation of info 786 786 String concatenation within initializer Although it is perfectly 'legal' to concatenate string constants within an initializer, this is a frequent source of error. Consider: char *s[] = { "abc" "def" }; Did the programmer intend to have an array of two strings but forget the comma separator? Or was a single string intended?

Example 5 The code is supposed to return the sum of all elements of a matrix #include <stdio.h> int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9} }; int sum( int a[3][3] ) { int i=0, j=0, k=0; for( i = 0; i < 3; i++ ) { k += a[i][j]; } return k; int main() { printf( "The triangular sum is %d\n", sum(a) ); // displays 12 return 0;

Analysing example 5 1  #include <stdio.h> 2   3  int a[3][3] = { {1,2,3}, {4,5,6}, {7,8,9} };                                _ 4  int sum( int a[3][3] ) { diy.cpp  4  Warning 578:  Declaration of symbol 'a' hides symbol 'a' (line 3) 5    int i=0, j=0, k=0;                     _ 6    for( i = 0; i < 3; i++ ) { diy.cpp  6  Info 838:  Previously assigned value to variable 'i' has not been used                                      _ 7        for( i = 0; i < 3; i++ ) { diy.cpp  7  Warning 445:  Reuse of for loop variable 'i' at 'line 6' could cause chaos 8     k += a[i][j]; 9    } 10    }           _ 11    return k; diy.cpp  11  Info 850:  for loop index variable 'i' whose type category is 'integral' is modified in body of the for loop that began at 'line 6'         _ 12  } diy.cpp  12  Info 818:  Pointer parameter 'a' (line 4) could be declared as pointing to const 13   14  int main() { 15    printf( "The triangular sum is %d\n", sum(a) ); 16    return 0; 17  }

Explanation of warning 445 445 reuse of for loop variable 'Symbol' at 'Location' could cause chaos A for loop nested within another for loop employed the same loop variable. For example: for( i = 0; i < 100; i++ ) { ... for( i = 0; i < n; i++ ) { ... } }

Example 6 //lint -passes(4) int f( int n ) { return 10/n; } int g( int n ) if( n == -1 ) return 0; return f(n) + g( n - 1 ); int main() return g( 3 ); // a crash appears

Analysing example 6 /// Start of Pass 4 /// --- Module: diy.cpp (C++)      1  //lint -passes(4)      2        3  int f( int n )      4      {      5      return 10/n; During Specific Walk: diy.cpp  16  g(3) #2 diy.cpp  11  g(2) #3 diy.cpp  11  g(1) #4 diy.cpp  11  g(0) #5 diy.cpp  11  f(0) #5 diy.cpp  5  Warning 414:  Possible division by 0 [Reference: file diy.cpp: lines 11, 16]      6      }      7        8  int g( int n )      9      {     10      if( n == -1 ) return 0;     11      return f(n) + g( n - 1 );     12      }     13       14  int main()     15      {     16      return g( 3 );     17      }

Explanation of warning 414 414 Possible division by 0 The second argument to either the division operator (/) or the modulus operator (%) may be zero. Information is taken from earlier statements including assignments, initialization and tests.

Example 7 #include <stdio.h> struct { int bit:1; } s; bool f() { if( s.bit > 0 ) return true; else return false; } int main() { s.bit = 1; if( f() ) printf( "the bit is ON\n" ); else printf( "the bit is OFF\n" ); // this is what is displayed return 0;

Analysing example 7 1  #include <stdio.h>      2                           _      3  struct { int bit:1; } s; diy.cpp  3  Info 846:  Signedness of bit-field is implementation defined diy.cpp  3  Info 806:  Small bit field is signed rather than unsigned      4        5  bool f() {                         _      6    if( s.bit > 0 ) return true; diy.cpp  6  Warning 685:  Relational operator '>' always evaluates to 'false'      7    else return false;      8  }      9       10  int main() {                    _     11    s.bit = 1; diy.cpp  11  Warning 542:  Excessive size for bit field     12    if( f() ) printf( "the bit is ON\n" );     13    else printf( "the bit is OFF\n" );     14    return 0;     15  } s.bit est signé et peut valoir 0 ou -1 uniquement

Explanation of info 846 A bit-field was detected having the form: 846 Signedness of bit-field is implementation defined A bit-field was detected having the form: int a:5; Most bit fields are more useful when they are unsigned. If you want to have a signed bit field you must explicitly indicate this as follows: signed int a:5; The same also holds for typedef's. For example, typedef int INT; typedef signed int SINT; struct { INT a:16; // Info 846 SINT b:16; // OK }: It is very unusual in C or C++ to distinguish between signed int and just plain int. This is one of those rare cases. s.bit est signé et peut valoir 0 ou -1 uniquement

Example 8 #include <stdio.h> struct { int a[3], b; } w[] = { { 1, 2, 3 }, 2 }; int main() { printf( "w[0].b = %d\n", w[0].b ); // displays 0 return 0; }

Analysing example 8 1 #include <stdio.h> 2 2                                             3  struct { int a[3], b; } w[] = { { 1, 2, 3 }, 2 }; diy.cpp  3  Warning 651:  Potentially confusing initializer diy.cpp  3  Info 785:  Too few initializers for aggregate 'unknown-name‘ of type '{...}‘ diy.cpp  3  Info 785:  Too few initializers for aggregate 'unknown-name‘ of type 'int [3]‘ diy.cpp  3  Info 785:  Too few initializers for aggregate 'unknown-name‘ of type '{...} 4   5  int main() 6  { 7    printf( "w[0].b = %d\n", w[0].b ); 8    return 0; 9  }

Explanation of warning 651 651 Potentially confusing initializer An initializer for a complex aggregate is being processed that contains some subaggregates that are bracketed and some that are not. ANSI recommends either "minimally bracketed" initializers in which there are no interior braces or "fully bracketed" initializers in which all interior aggregates are bracketed.

Example 9 class X { public: int upper; int lower; X( int init ) : lower( init ), upper( lower+1 ) {} }; X x(1); // x.upper is equal to 1 instead of 2

Analysing example 9 1  class X 2  { 3  public: 4    int upper; 5    int lower; 6    X( int init ) : lower( init ), upper( lower+1 ) 7    {}                                               _ 6    X( int init ) : lower( init ), upper( lower+1 ) diy.cpp  6  Info 1729:  Initializer inversion detected for member 'X::upper'         _ 8  }; diy.cpp  8  Info 1712:  default constructor not defined for class 'X' 9   10  X x(1);

Explanation of info 1729 1729 Initializer inversion detected for member 'Symbol‘ In a constructor initializer the order of evaluation is determined by the member order not the order in which the initializers are given. At least one of the initializers was given out of order. Was there a reason for this? Did the programmer think that by changing the order that he/she would affect the order of evaluation? Place the initializers in the order of their occurrence within the class so that there can be no mistaken assumptions.

Example 10 #include <iostream> using namespace std; struct WhiteHouse { int *p; WhiteHouse(int n) { p = new int; *p = n; } ~WhiteHouse() { delete p; } }; WhiteHouse ww(1912); void f() { WhiteHouse fdr(1932); fdr = ww; } int main() { f(); WhiteHouse gwb(2000); cout << *ww.p; // crash or displays 2000 return 0; }

Analysing example 10   1  #include <iostream> 2  using namespace std; 3   4  struct WhiteHouse { 5    int *p; 6    WhiteHouse(int n) { p = new int; *p = n; } 7    ~WhiteHouse() { delete p; }                                   _ 6    WhiteHouse(int n) { p = new int; *p = n; } diy.cpp  6  Info 1732:  new in constructor for class 'WhiteHouse' which has no assignment operator diy.cpp  6  Info 1733:  new in constructor for class 'WhiteHouse' which has no copy constructor         _ 8  }; diy.cpp  8  Info 1712:  default constructor not defined for class 'WhiteHouse' 9   10  WhiteHouse ww(1912); 11   12  void f() { WhiteHouse fdr(1932); fdr = ww; } 13   14  int main() { 15    f(); 16    WhiteHouse gwb(2000); 17    cout << *ww.p;         // crash or displays 2000 18    return 0;         _ 19  } diy.cpp  19  Info 1788:  Variable 'gwb' (line 16) (type 'WhiteHouse') is referenced only by its constructor or destructor

Explanation of info 1732 1732 new in constructor for class 'Name' which has no assignment operator Within a constructor for the cited class, there appeared a new. However, no assignment operator was declared for this class. Presumably some class member (or members) points to dynamically allocated memory. Such memory is not treated properly by the default assignment operator. Normally a custom assignment operator would be needed. Thus, if x and y are both of type Name x = y; will result in pointer duplication. A later delete would create chaos.