This updates StdLibraryFunctionsChecker to set the state of 'errno' by using the new errno_modeling functionality. The errno value is set in the PostCall callback. Setting it in call::Eval did not work for some reason and then every function should be EvalCallAsPure which may be bad to do. Now the errno value and state is not allowed to be checked in any PostCall checker callback because it is unspecified if the errno was set already or will be set later by this checker. Reviewed By: martong, steakhal Differential Revision: https://reviews.llvm.org/D125400
57 lines
1.7 KiB
C
57 lines
1.7 KiB
C
// RUN: %clang_analyze_cc1 -verify %s \
|
|
// RUN: -analyzer-checker=core \
|
|
// RUN: -analyzer-checker=debug.ExprInspection \
|
|
// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \
|
|
// RUN: -analyzer-checker=apiModeling.Errno \
|
|
// RUN: -analyzer-checker=alpha.unix.Errno \
|
|
// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true
|
|
|
|
#include "Inputs/errno_var.h"
|
|
|
|
typedef typeof(sizeof(int)) size_t;
|
|
typedef __typeof(sizeof(int)) off_t;
|
|
typedef size_t ssize_t;
|
|
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
|
|
off_t lseek(int fildes, off_t offset, int whence);
|
|
|
|
void clang_analyzer_warnIfReached();
|
|
void clang_analyzer_eval(int);
|
|
|
|
int unsafe_errno_read(int sock, void *data, int data_size) {
|
|
if (send(sock, data, data_size, 0) != data_size) {
|
|
if (errno == 1) {
|
|
// expected-warning@-1{{An undefined value may be read from 'errno'}}
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int errno_lseek(int fildes, off_t offset) {
|
|
off_t result = lseek(fildes, offset, 0);
|
|
if (result == (off_t)-1) {
|
|
// Failure path.
|
|
// check if the function is modeled
|
|
clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
|
|
return 2;
|
|
}
|
|
if (result != offset) {
|
|
// Not success path (?)
|
|
// not sure if this is a valid case, allow to check 'errno'
|
|
if (errno == 1) { // no warning
|
|
return 1;
|
|
}
|
|
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
|
|
}
|
|
if (result == offset) {
|
|
// The checker does not differentiate for this case.
|
|
// In general case no relation exists between the arg 2 and the returned
|
|
// value, only for SEEK_SET.
|
|
if (errno == 1) { // no warning
|
|
return 1;
|
|
}
|
|
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
|
|
}
|
|
return 0;
|
|
}
|