|
|
|
/*
|
|
|
|
* Copyright (c) 2009 - 2013 Monoidics ltd.
|
|
|
|
* Copyright (c) 2013 - present Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Basic modelling of some libc functions
|
|
|
|
|
|
|
|
// prevent _FORTIFY_SOURCE from changing some function prototypes
|
|
|
|
// https://securityblog.redhat.com/2014/03/26/fortify-and-you/
|
|
|
|
#ifdef _FORTIFY_SOURCE
|
|
|
|
#undef _FORTIFY_SOURCE
|
|
|
|
#endif
|
|
|
|
#define _FORTIFY_SOURCE 0
|
|
|
|
|
|
|
|
#ifdef __APPLE__ // disable block instructions on mac
|
|
|
|
#ifdef __BLOCKS__
|
|
|
|
#undef __BLOCKS__
|
|
|
|
#endif
|
|
|
|
#ifdef _POSIX_C_SOURCE
|
|
|
|
#undef _POSIX_C_SOURCE
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "infer_builtins.h"
|
|
|
|
|
|
|
|
// use c++ headers if in C++ mode - they are mostly same as C headers,
|
|
|
|
// but there are some subtle differences from time to time. For example,
|
|
|
|
// 'getc' may be defined as macro in stdio.h, and a function in cstdio
|
|
|
|
#ifdef __cplusplus
|
|
|
|
#include <climits>
|
|
|
|
#include <clocale>
|
|
|
|
#include <csetjmp>
|
|
|
|
#include <cstdarg>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <csignal>
|
|
|
|
#else
|
|
|
|
#include <limits.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <sys/shm.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#ifdef __APPLE__ // includes for statfs are system-dependent
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#else
|
|
|
|
#include <sys/statfs.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __APPLE__
|
|
|
|
/* struct __dirstream is abstract on Linux, at least on Debian 8.0
|
|
|
|
we need it to be concrete to model closedir (5) */
|
|
|
|
/* dummy __dirstream structure */
|
|
|
|
struct __dirstream {
|
|
|
|
int fd;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// this condition checks whether to use C++ const-overloads of C functions
|
|
|
|
// for example strchr.
|
|
|
|
#if defined(__CORRECT_ISO_CPP_STRING_H_PROTO) || \
|
|
|
|
defined(_LIBCPP_PREFERRED_OVERLOAD)
|
|
|
|
#define INFER_USE_CPP_CONST_OVERLOAD
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// modelling of errno
|
|
|
|
// errno expands to different function calls on mac or other systems
|
|
|
|
// the function call returns the address of a global variable called "errno"
|
|
|
|
extern int errno;
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#define __ERRNO_FUN_NAME __error
|
|
|
|
#else
|
|
|
|
#define __ERRNO_FUN_NAME __errno_location
|
|
|
|
#endif
|
|
|
|
int* __ERRNO_FUN_NAME() { return &errno; }
|
|
|
|
|
|
|
|
// the strings s1 and s2 need to be allocated
|
|
|
|
// check that s2 fits inside s1
|
|
|
|
char* strcpy(char* s1, const char* s2) {
|
|
|
|
int size1;
|
|
|
|
int size2;
|
|
|
|
__infer_set_flag("ignore_return",
|
|
|
|
""); // no warnings if the return value is ignored
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size2 = __get_array_length(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION(size2 > size1);
|
|
|
|
return s1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the string s must be allocated; return the result of malloc with the same
|
|
|
|
// size
|
|
|
|
char* strdup(const char* s) {
|
|
|
|
int size;
|
|
|
|
__require_allocated_array(s);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size = __get_array_length(s);
|
|
|
|
return (char*)malloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
// the strings s1 and s2 need to be allocated
|
|
|
|
// check that s2 fits inside s1
|
|
|
|
char* strcat(char* s1, const char* s2) {
|
|
|
|
int size1;
|
|
|
|
int size2;
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size2 = __get_array_length(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION(size2 > size1);
|
|
|
|
return s1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++ has two versions of strchr:
|
|
|
|
// http://www.cplusplus.com/reference/cstring/strchr/
|
|
|
|
// C has one version of strchr/strrchr with different signature
|
|
|
|
|
|
|
|
// The string s must be allocated
|
|
|
|
// nondeterministically return 0 or a pointer inside the buffer
|
|
|
|
#ifndef INFER_USE_CPP_CONST_OVERLOAD
|
|
|
|
char* strchr(const char* s, int c) {
|
|
|
|
#else
|
|
|
|
// This overload is commented out on purpose.
|
|
|
|
// Standard headers define both functions with same __asm symbol which
|
|
|
|
// means they cannot be both defined. On the other hand, since both of them
|
|
|
|
// have same __asm symbol, mangling will be the same and infer will have
|
|
|
|
// specs for both functions (they both will have the same name)
|
|
|
|
// NOTE: this was tested on couple of systems, it may not be always true.
|
|
|
|
// const char* strchr(const char* s, int c) throw() { return strchr((char*)s,
|
|
|
|
// c); }
|
|
|
|
|
|
|
|
char* strchr(char* s, int c) throw() {
|
|
|
|
#endif
|
|
|
|
int size;
|
|
|
|
int nondet;
|
|
|
|
int offset;
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
offset = __infer_nondet_int();
|
|
|
|
|
|
|
|
__require_allocated_array(s);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size = __get_array_length(s);
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(offset < 0 || offset >= size);
|
|
|
|
return (char*)s + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modelled like strchr
|
|
|
|
#ifndef INFER_USE_CPP_CONST_OVERLOAD
|
|
|
|
char* strrchr(const char* s, int c) { return strchr(s, c); }
|
|
|
|
#else
|
|
|
|
// This overload is commented out on purpose. Look at strchr() for more info.
|
|
|
|
/*const char* strrchr(const char* s, int c) throw() {
|
|
|
|
return strchr((char*)s, c);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
char* strrchr(char* s, int c) throw() { return strchr(s, c); }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// s1 and s2 must be allocated.
|
|
|
|
// return a non-deterministic integer
|
|
|
|
int strcmp(const char* s1, const char* s2) {
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
|
|
|
|
__require_allocated_array(s1);
|
|
|
|
__require_allocated_array(s2);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the string s must be allocated
|
|
|
|
// return the size of the buffer - 1
|
|
|
|
size_t strlen(const char* s) {
|
|
|
|
int size;
|
|
|
|
__require_allocated_array(s);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size = __get_array_length(s);
|
|
|
|
return size - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s must be allocated
|
|
|
|
// return s
|
|
|
|
char* strlwr(char* s) {
|
|
|
|
__require_allocated_array(s);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s1 and s2 must be allocated
|
|
|
|
// n should not be greater than the size of s1 or s2
|
|
|
|
// return s1
|
|
|
|
char* strncat(char* s1, const char* s2, size_t n) {
|
|
|
|
int size_s1;
|
|
|
|
int size_s2;
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s2 = __get_array_length(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION((n > size_s1) || (n > size_s2));
|
|
|
|
return s1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s1 and s2 must be allocated
|
|
|
|
// n should not be greater than the size of s1 or s2
|
|
|
|
// return a non-deterministic integer
|
|
|
|
int strncmp(const char* s1, const char* s2, size_t n) {
|
|
|
|
int size_s1;
|
|
|
|
int size_s2;
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s2 = __get_array_length(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION((n > size_s1) || (n > size_s2));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the strings s1 and s2 need to be allocated
|
|
|
|
// check that n characters fit in s1 (because even if s2 is shorter than n, null
|
|
|
|
// characters are appended to s1)
|
|
|
|
char* strncpy(char* s1, const char* s2, size_t n) {
|
|
|
|
int size1;
|
|
|
|
__infer_set_flag("ignore_return",
|
|
|
|
""); // no warnings if the return value is ignored
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION(n > size1);
|
|
|
|
return s1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef INFER_USE_CPP_CONST_OVERLOAD
|
|
|
|
char* strpbrk(const char* s1, const char* s2) {
|
|
|
|
#else
|
|
|
|
// This overload is commented out on purpose. Look at strchr() for more info.
|
|
|
|
/*const char* strpbrk(const char* s1, const char* s2) throw() {
|
|
|
|
return strpbrk((char*)s1, s2);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
char* strpbrk(char* s1, const char* s2) throw() {
|
|
|
|
#endif
|
|
|
|
int size1;
|
|
|
|
int nondet;
|
|
|
|
int offset;
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
offset = __infer_nondet_int();
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(offset < 0 || offset >= size1);
|
|
|
|
return (char*)s1 + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s1 and s2 must be allocated.
|
|
|
|
// return an integer between 0 ans the size of s1
|
|
|
|
size_t strspn(const char* s1, const char* s2) {
|
|
|
|
int size_s1;
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0 || res > size_s1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef INFER_USE_CPP_CONST_OVERLOAD
|
|
|
|
char* strstr(const char* s1, const char* s2) {
|
|
|
|
#else
|
|
|
|
// This overload is commented out on purpose. Look at strchr() for more info.
|
|
|
|
/*const char* strstr(const char* s1, const char* s2) throw() {
|
|
|
|
return strstr((char*)s1, s2);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
char* strstr(char* s1, const char* s2) throw() {
|
|
|
|
#endif
|
|
|
|
int size1, size2;
|
|
|
|
int nondet;
|
|
|
|
int offset;
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
offset = __infer_nondet_int();
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(offset < 0 || offset >= size1);
|
|
|
|
return (char*)s1 + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using strtoul
|
|
|
|
double strtod(const char* str, char** endptr) {
|
|
|
|
return (double)strtoul(str, endptr, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled like strtoul
|
|
|
|
long strtol(const char* str, char** endptr, int base) {
|
|
|
|
return (long)strtoul(str, endptr, base);
|
|
|
|
}
|
|
|
|
|
|
|
|
// the string s must be allocated
|
|
|
|
// assign to endptr a pointer somewhere inside the string str
|
|
|
|
// result is nondeterministic
|
|
|
|
unsigned long strtoul(const char* str, char** endptr, int base) {
|
|
|
|
int size;
|
|
|
|
int offset;
|
|
|
|
int res;
|
|
|
|
__require_allocated_array(str);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size = __get_array_length(str);
|
|
|
|
offset = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(offset < 0 || offset >= size);
|
|
|
|
if (endptr)
|
|
|
|
*endptr = (char*)(str + offset);
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
int errno_val = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(errno_val < 0);
|
|
|
|
errno = errno_val;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s must be allocated
|
|
|
|
// return s
|
|
|
|
char* strupr(char* s) {
|
|
|
|
__require_allocated_array(s);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the array s must be allocated
|
|
|
|
// n should not be greater than the size of s
|
|
|
|
// nondeterministically return 0 or a pointer within the first n elements of s
|
|
|
|
#ifndef INFER_USE_CPP_CONST_OVERLOAD
|
|
|
|
void* memchr(const void* s, int c, size_t n) {
|
|
|
|
#else
|
|
|
|
// This overload is commented out on purpose. Look at strchr() for more info.
|
|
|
|
// const void* memchr(const void* s, int c, size_t n) throw() {
|
|
|
|
// return memchr((void*)s, c, n);
|
|
|
|
//}
|
|
|
|
|
|
|
|
void* memchr(void* s, int c, size_t n) throw() {
|
|
|
|
#endif
|
|
|
|
int size;
|
|
|
|
int nondet;
|
|
|
|
int offset;
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
offset = __infer_nondet_int();
|
|
|
|
__require_allocated_array(s);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size = __get_array_length(s);
|
|
|
|
INFER_EXCLUDE_CONDITION(n > size);
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(offset < 0 || offset >= n);
|
|
|
|
return (char*)s + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s1 and s2 must be allocated
|
|
|
|
// n should not be greater than the size of s1 or s2
|
|
|
|
// return a non-deterministic integer
|
|
|
|
int memcmp(const void* s1, const void* s2, size_t n) {
|
|
|
|
int size_s1;
|
|
|
|
int size_s2;
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s2 = __get_array_length(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION((n > size_s1) || (n > size_s2));
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// s1 and s2 must be allocated
|
|
|
|
// n must be between 0 and the minumum of the sizes of s1 and s2
|
|
|
|
void* memcpy(void* s1, const void* s2, size_t n) {
|
|
|
|
int size_s1;
|
|
|
|
int size_s2;
|
|
|
|
__infer_set_flag("ignore_return",
|
|
|
|
""); // no warnings if the return value is ignored
|
|
|
|
__require_allocated_array(s1);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s1 = __get_array_length(s1);
|
|
|
|
__require_allocated_array(s2);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s2 = __get_array_length(s2);
|
|
|
|
INFER_EXCLUDE_CONDITION((n < 0) || (n > size_s1) || (n > size_s2));
|
|
|
|
return s1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeld using memcpy
|
|
|
|
void* memmove(void* s1, const void* s2, size_t n) {
|
|
|
|
__infer_set_flag("ignore_return",
|
|
|
|
""); // no warnings if the return value is ignored
|
|
|
|
return memcpy(s1, s2, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
// s needs to be allocated
|
|
|
|
// n should not be greater than the size of s
|
|
|
|
void* memset(void* s, int c, size_t n) {
|
|
|
|
int size_s;
|
|
|
|
__infer_set_flag("ignore_return",
|
|
|
|
""); // no warnings if the return value is ignored
|
|
|
|
__require_allocated_array(s);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_s = __get_array_length(s);
|
|
|
|
INFER_EXCLUDE_CONDITION(n > size_s);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic double
|
|
|
|
double atof(const char* str) { return __infer_nondet_double(); }
|
|
|
|
|
|
|
|
// return a nondeterministic value between INT_MIN and INT_MAX
|
|
|
|
int atoi(const char* str) {
|
|
|
|
int retu = INT_MAX;
|
|
|
|
int retl = INT_MIN;
|
|
|
|
int ret;
|
|
|
|
if (__infer_nondet_int())
|
|
|
|
ret = retu;
|
|
|
|
else
|
|
|
|
ret = retl;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using malloc and set file attribute
|
|
|
|
FILE* fopen(const char* filename, const char* mode) {
|
|
|
|
FILE* ret;
|
|
|
|
ret = (FILE*)malloc(sizeof(FILE));
|
|
|
|
if (ret)
|
|
|
|
__set_file_attribute(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using fopen
|
|
|
|
FILE* tmpfile(void) { return fopen("foo", ""); }
|
|
|
|
|
|
|
|
// use a global variable to model the return value of tmpnam
|
|
|
|
extern char* _tmpnam_global;
|
|
|
|
// return NULL, or if s is NULL return a global variable, otherwise check that s
|
|
|
|
// has size at least L_tmpnam and return s
|
|
|
|
char* tmpnam(char* s) {
|
|
|
|
int success;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
if (!success)
|
|
|
|
return NULL;
|
|
|
|
if (s) {
|
|
|
|
__require_allocated_array(s);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size = __get_array_length(s);
|
|
|
|
INFER_EXCLUDE_CONDITION(size < L_tmpnam);
|
|
|
|
return s;
|
|
|
|
} else
|
|
|
|
return _tmpnam_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nondeterministically return NULL or the original stream
|
|
|
|
FILE* freopen(const char* __restrict filename,
|
|
|
|
const char* __restrict mode,
|
|
|
|
FILE* __restrict stream) {
|
|
|
|
int n;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using free, can return EOF
|
|
|
|
int fclose(FILE* stream) {
|
|
|
|
int n;
|
|
|
|
free(stream);
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n > 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using malloc and set file attribute
|
|
|
|
// return the allocated ptr - 1 if malloc succeeds, otherwise return -1
|
|
|
|
int open(const char* path, int oflag, ...) {
|
|
|
|
int* ret = (int*)malloc(sizeof(int));
|
|
|
|
if (ret) {
|
|
|
|
__set_file_attribute(ret);
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < (int*)1); // force result to be > 0
|
|
|
|
return (size_t)ret;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using free, can return -1
|
|
|
|
int close(int fildes) {
|
|
|
|
int n;
|
|
|
|
if (fildes != -1)
|
|
|
|
free((int*)(long)fildes);
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n > 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled as close followed by fopen
|
|
|
|
FILE* fdopen(int fildes, const char* mode) {
|
|
|
|
close(fildes);
|
|
|
|
return fopen("foo", mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using fdopen
|
|
|
|
FILE* gzdopen(int fildes, const char* mode) { return fdopen(fildes, mode); }
|
|
|
|
|
|
|
|
// return nonteterministically 0 or -1
|
|
|
|
// requires stream to be allocated
|
|
|
|
int fseek(FILE* stream, long int offset, int whence) {
|
|
|
|
int n;
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return nondeterministically a nonnegative value or -1
|
|
|
|
// requires stream to be allocated
|
|
|
|
long int ftell(FILE* stream) {
|
|
|
|
int n;
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n >= 0)
|
|
|
|
return n;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// on success return str otherwise null
|
|
|
|
// requires stream to be allocated
|
|
|
|
char* fgets(char* str, int num, FILE* stream) {
|
|
|
|
int n;
|
|
|
|
int size1;
|
|
|
|
FILE tmp;
|
|
|
|
|
|
|
|
tmp = *stream;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
__require_allocated_array(str);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size1 = __get_array_length(str);
|
|
|
|
INFER_EXCLUDE_CONDITION(num > size1);
|
|
|
|
return str;
|
|
|
|
} else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// string s must be allocated; return nondeterministically s or NULL
|
|
|
|
char* gets(char* s) {
|
|
|
|
int n;
|
|
|
|
|
|
|
|
__require_allocated_array(s);
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n)
|
|
|
|
return s;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// str must be allocated, return a nondeterministic value
|
|
|
|
int puts(const char* str) {
|
|
|
|
__require_allocated_array(str);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using puts
|
|
|
|
// require the stream to be allocated
|
|
|
|
int fputs(const char* str, FILE* stream) {
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
return puts(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
// requires stream to be allocated
|
|
|
|
int getc(FILE* stream) {
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
// requires stream to be allocated
|
|
|
|
int fgetc(FILE* stream) {
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// return nondeterministically c or EOF
|
|
|
|
// requires stream to be allocated
|
|
|
|
int ungetc(int c, FILE* stream) {
|
|
|
|
int n;
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n)
|
|
|
|
return c;
|
|
|
|
else
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled like putc
|
|
|
|
// requires stream to be allocated
|
|
|
|
int fputc(int c, FILE* stream) {
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
return putc(c, stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
// on success return buffer otherwise null
|
|
|
|
char* getcwd(char* buffer, size_t size) {
|
|
|
|
int n;
|
|
|
|
int size_buf;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
__require_allocated_array(buffer);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_buf = __get_array_length(buffer);
|
|
|
|
INFER_EXCLUDE_CONDITION(size > size_buf);
|
|
|
|
return buffer;
|
|
|
|
} else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return nonteterministically 0 or -1
|
|
|
|
int rename(const char* old, const char* new_) {
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled as skip
|
|
|
|
// requires stream to be allocated
|
|
|
|
void rewind(FILE* stream) {
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled as exit()
|
|
|
|
void longjmp(jmp_buf env, int val) { exit(0); }
|
|
|
|
|
|
|
|
// modeled as skip.
|
|
|
|
// If sleep() returns because the requested time has elapsed,
|
|
|
|
// the value returned shall be 0. If sleep() returns due to delivery of a
|
|
|
|
// signal,
|
|
|
|
// the return value shall be the "unslept" amount (the requested time minus the
|
|
|
|
// time actually slept) in seconds.
|
|
|
|
unsigned sleep(unsigned seconds) {
|
|
|
|
int n;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(n < 0);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __CYGWIN__ // define __WAIT_STATUS as int * on cygwin
|
|
|
|
#define __WAIT_STATUS int*
|
|
|
|
#endif
|
|
|
|
#ifdef __APPLE__ // define __WAIT_STATUS as int * on mac
|
|
|
|
#define __WAIT_STATUS int*
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// glibc 2.24 did away with 'union wait' and replaced it with int*.
|
|
|
|
// Hence, we re-define __WAIT_STATUS if glibc is >= 2.24.
|
|
|
|
#ifndef __GLIBC_PREREQ
|
|
|
|
#define __GLIBC_PREREQ(x, y) 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 24)
|
|
|
|
#define __WAIT_STATUS int*
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// the waiting is modeled as skip. Then the return value is a random value of a
|
|
|
|
// process or
|
|
|
|
// -1 in case of an error
|
|
|
|
pid_t wait(__WAIT_STATUS stat_loc) {
|
|
|
|
int n;
|
|
|
|
pid_t tmp;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
tmp = __infer_nondet_int();
|
|
|
|
if (n > 0)
|
|
|
|
return tmp;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef __cplusplus
|
|
|
|
// return a nondeterministic pointer
|
|
|
|
void (*signal(int sig, void (*func)(int)))(int) {
|
|
|
|
void (*res)(int) = __infer_nondet_ptr();
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// modelled as exit
|
|
|
|
void pthread_exit(void* value_ptr) { exit(0); };
|
|
|
|
|
|
|
|
// INTENDED SEMANTICS: The setitimer() function shall set the timer specified by
|
|
|
|
// which
|
|
|
|
// to the value specified in the structure pointed to by value, and if ovalue is
|
|
|
|
// not a null pointer,
|
|
|
|
// store the previous value of the timer in the structure pointed to by ovalue.
|
|
|
|
int setitimer(int which,
|
|
|
|
const struct itimerval* __restrict value,
|
|
|
|
struct itimerval* __restrict ovalue) {
|
|
|
|
int n;
|
|
|
|
int tmp;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
tmp = __infer_nondet_int();
|
|
|
|
// not sure about this assignment.
|
|
|
|
// it should somehow change the value of the timer which.
|
|
|
|
// But which is just an int, so it looks like this is useless
|
|
|
|
which = tmp;
|
|
|
|
if (n > 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// pause returns only when a signal is received
|
|
|
|
// the return value is always -1
|
|
|
|
int pause(void) { return -1; }
|
|
|
|
|
|
|
|
// modeled with nondeterministic value n
|
|
|
|
pid_t fork(void) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
// allocate memory directly, and return -1 if malloc fails.
|
|
|
|
int shmget(key_t key, size_t size, int shmflg) {
|
|
|
|
void* res = malloc(size);
|
|
|
|
if (!res)
|
|
|
|
return -1;
|
|
|
|
return (long)res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// simply return the first parameter
|
|
|
|
void* shmat(int shmid, const void* shmaddr, int shmflg) {
|
|
|
|
return (void*)(long)shmid;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a non-deterministic value
|
|
|
|
int shmdt(const void* shmaddr) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
// if the command is IPC_RMID free the first parameter; return a
|
|
|
|
// non-deterministic value
|
|
|
|
int shmctl(int shmid, int cmd, struct shmid_ds* buf) {
|
|
|
|
int n;
|
|
|
|
void* shmaddr;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
shmaddr = (void*)(long)shmid;
|
|
|
|
if (cmd == IPC_RMID)
|
|
|
|
free(shmaddr);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* realloc(void* ptr, size_t size) {
|
|
|
|
if (ptr == 0) { // if ptr in NULL, behave as malloc
|
|
|
|
return malloc(size);
|
|
|
|
}
|
|
|
|
int can_enlarge;
|
|
|
|
__require_allocated_array(ptr);
|
|
|
|
can_enlarge = __infer_nondet_int(); // nondeterministically choose whether the
|
|
|
|
// current block can be enlarged
|
|
|
|
if (can_enlarge) {
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
__set_array_length(ptr, size); // enlarge the block
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
int* newblock = (int*)malloc(size);
|
|
|
|
if (newblock) {
|
|
|
|
free(ptr);
|
|
|
|
return newblock;
|
|
|
|
} else { // if new allocation fails, do not free the old block
|
|
|
|
return newblock;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// modelled as a call to malloc
|
|
|
|
void* calloc(size_t nmemb, size_t size) { return malloc(nmemb * size); }
|
|
|
|
|
|
|
|
// character functions from ctype.h
|
|
|
|
// all modelled as returning a nondeterministic value
|
|
|
|
int isalnum(int x) { return __infer_nondet_int(); }
|
|
|
|
int isalpha(int x) { return __infer_nondet_int(); }
|
|
|
|
int isblank(int x) { return __infer_nondet_int(); }
|
|
|
|
int iscntrl(int x) { return __infer_nondet_int(); }
|
|
|
|
int isdigit(int x) { return __infer_nondet_int(); }
|
|
|
|
int isgraph(int x) { return __infer_nondet_int(); }
|
|
|
|
int islower(int x) { return __infer_nondet_int(); }
|
|
|
|
int isprint(int x) { return __infer_nondet_int(); }
|
|
|
|
int ispunct(int x) { return __infer_nondet_int(); }
|
|
|
|
int isspace(int x) { return __infer_nondet_int(); }
|
|
|
|
int isupper(int x) { return __infer_nondet_int(); }
|
|
|
|
int isxdigit(int x) { return __infer_nondet_int(); }
|
|
|
|
int tolower(int x) { return __infer_nondet_int(); }
|
|
|
|
int toupper(int x) { return __infer_nondet_int(); }
|
|
|
|
int isascii(int x) { return __infer_nondet_int(); }
|
|
|
|
int toascii(int x) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
// modeled as skip. n>0 models success.
|
|
|
|
// Upon successful completion a non-negative integer, namely the file
|
|
|
|
// descriptor, shall be returned;
|
|
|
|
// otherwise, -1 shall be returned.
|
|
|
|
int dup(int fildes) {
|
|
|
|
int n;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n > 0)
|
|
|
|
return fildes;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
// modeled as skip.
|
|
|
|
// The getuid() function shall always be successful and no return value is
|
|
|
|
// reserved to indicate the error.
|
|
|
|
uid_t getuid(void) { return __infer_nondet_int(); };
|
|
|
|
|
|
|
|
// modeled as skip
|
|
|
|
// The getpid() function shall always be successful and no return value is
|
|
|
|
// reserved to indicate an error.
|
|
|
|
pid_t getpid(void) { return __infer_nondet_int(); };
|
|
|
|
|
|
|
|
// modeled as skip.
|
|
|
|
// success is modeled by n>0, if lseek fails (off_t)-1 should be returned.
|
|
|
|
off_t lseek(int fildes, off_t offset, int whence) {
|
|
|
|
int n;
|
|
|
|
off_t tmp;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
tmp = __infer_nondet_int();
|
|
|
|
|
|
|
|
if (n > 0)
|
|
|
|
return tmp;
|
|
|
|
else
|
|
|
|
return (off_t)-1;
|
|
|
|
};
|
|
|
|
|
|
|
|
// modeled using malloc and set file attribute
|
|
|
|
DIR* opendir(const char* dirname) {
|
|
|
|
DIR* ret;
|
|
|
|
ret = (DIR*)malloc(sizeof(void*));
|
|
|
|
if (ret)
|
|
|
|
__set_file_attribute(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled using free, can return EOF
|
|
|
|
int closedir(DIR* dirp) {
|
|
|
|
DIR tmp = *dirp;
|
|
|
|
int n;
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
free(dirp);
|
|
|
|
if (n > 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of readdir
|
|
|
|
extern struct dirent* _dirent_global;
|
|
|
|
// dirp must be allocated
|
|
|
|
// return 0 or the allocated pointerq _dirent_global, nondeterministically
|
|
|
|
struct dirent* readdir(DIR* dirp) {
|
|
|
|
int nondet;
|
|
|
|
struct dirent* ret = _dirent_global;
|
|
|
|
__require_allocated_array(dirp);
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of getenv
|
|
|
|
extern char* _getenv_global;
|
|
|
|
// string name must be allocated
|
|
|
|
// return 0 or the allocated string _getenv_global, nondeterministically
|
|
|
|
char* getenv(const char* name) {
|
|
|
|
int nondet;
|
|
|
|
__require_allocated_array(name);
|
|
|
|
__require_allocated_array(_getenv_global);
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
return _getenv_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of setlocale
|
|
|
|
extern char* _locale_global;
|
|
|
|
// string locale must be allocated
|
|
|
|
// return 0 or the allocated string _locale_global, nondeterministically
|
|
|
|
char* setlocale(int category, const char* locale) {
|
|
|
|
int nondet;
|
|
|
|
__require_allocated_array(locale);
|
|
|
|
__require_allocated_array(_locale_global);
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
return _locale_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of localeconv
|
|
|
|
extern struct lconv* _lconv_global;
|
|
|
|
// return the allocated pointer _lconv_global
|
|
|
|
struct lconv* localeconv() {
|
|
|
|
int nondet;
|
|
|
|
struct lconv tmp;
|
|
|
|
tmp = *_lconv_global;
|
|
|
|
return _lconv_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of localtime
|
|
|
|
extern struct tm* _tm_global;
|
|
|
|
// return nondeterministically NULL or the global variable _tm_global
|
|
|
|
struct tm* localtime(const time_t* clock) {
|
|
|
|
int fail;
|
|
|
|
|
|
|
|
fail = __infer_nondet_int();
|
|
|
|
if (fail)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return _tm_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return nondeterministically NULL or the global variable _tm_global
|
|
|
|
struct tm* gmtime(const time_t* timer) {
|
|
|
|
int fail;
|
|
|
|
|
|
|
|
fail = __infer_nondet_int();
|
|
|
|
if (fail)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return _tm_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of asctime
|
|
|
|
extern char* _asctime_global;
|
|
|
|
// return the global variable _asctime_global
|
|
|
|
char* asctime(const struct tm* timeptr) { return _asctime_global; }
|
|
|
|
|
|
|
|
// modelled using asctime and localtime
|
|
|
|
char* ctime(const time_t* clock) { return asctime(localtime(clock)); }
|
|
|
|
|
|
|
|
// return a nondeterministic double
|
|
|
|
double difftime(time_t time1, time_t time0) { return __infer_nondet_double(); }
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative value or -1
|
|
|
|
time_t mktime(struct tm* timeptr) {
|
|
|
|
time_t res;
|
|
|
|
res = __infer_nondet_time_t();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < -1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative value or -1
|
|
|
|
clock_t clock() {
|
|
|
|
clock_t res;
|
|
|
|
res = __infer_nondet_clock_t();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < -1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative value
|
|
|
|
size_t strftime(char* __restrict s,
|
|
|
|
size_t maxsize,
|
|
|
|
const char* __restrict format,
|
|
|
|
const struct tm* __restrict timeptr) {
|
|
|
|
size_t res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic value of type time_t
|
|
|
|
time_t time(time_t* tloc) {
|
|
|
|
time_t t;
|
|
|
|
t = __infer_nondet_time_t();
|
|
|
|
if (tloc)
|
|
|
|
*tloc = t;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of getpwuid
|
|
|
|
extern struct passwd* _getpwuid_global;
|
|
|
|
// return either NULL or the global variable _getpwuid_global
|
|
|
|
struct passwd* getpwuid(uid_t uid) {
|
|
|
|
int found;
|
|
|
|
found = __infer_nondet_int();
|
|
|
|
if (found)
|
|
|
|
return _getpwuid_global;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of getpwent
|
|
|
|
extern struct passwd* _getpwent_global;
|
|
|
|
// return either NULL or the global variable _getpwent_global
|
|
|
|
struct passwd* getpwent(void) {
|
|
|
|
int found;
|
|
|
|
found = __infer_nondet_int();
|
|
|
|
if (found)
|
|
|
|
return _getpwent_global;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of getpwnam
|
|
|
|
extern struct passwd* _getpwnam_global;
|
|
|
|
// login must be allocated
|
|
|
|
// return either NULL or the global variable _getpnam_global
|
|
|
|
struct passwd* getpwnam(const char* login) {
|
|
|
|
int found;
|
|
|
|
__require_allocated_array(login);
|
|
|
|
found = __infer_nondet_int();
|
|
|
|
if (found)
|
|
|
|
return _getpwnam_global;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nondeterministically return 0 (failure) or 1 (success)
|
|
|
|
int setpassent(int stayopen) {
|
|
|
|
int success;
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
if (success)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modled as skip
|
|
|
|
void setpwent(void) {}
|
|
|
|
|
|
|
|
// modled as skip
|
|
|
|
void endpwent(void) {}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of getlogin
|
|
|
|
extern char* _getlogin_global;
|
|
|
|
// string name must be allocated
|
|
|
|
// return 0 or the allocated string _getlogin_global, nondeterministically
|
|
|
|
char* getlogin() {
|
|
|
|
int size;
|
|
|
|
int nondet;
|
|
|
|
__require_allocated_array(_getlogin_global);
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
return _getlogin_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
int setlogin(const char* name) {
|
|
|
|
int success;
|
|
|
|
__require_allocated_array(name);
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
if (success) {
|
|
|
|
strcpy(_getlogin_global, name);
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// use a global variable to model the return value of getpass
|
|
|
|
extern char* _getpass_global;
|
|
|
|
// prompt must be allocated
|
|
|
|
// return the global variable _getpass_global, which must be allocated
|
|
|
|
char* getpass(const char* prompt) {
|
|
|
|
__require_allocated_array(prompt);
|
|
|
|
__require_allocated_array(_getpass_global);
|
|
|
|
return _getpass_global;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
int printf(const char* format, ...) {
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
// requires stream to be allocated
|
|
|
|
int fprintf(FILE* stream, const char* format, ...) {
|
|
|
|
int res;
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
int snprintf(char* __restrict s, size_t n, const char* __restrict format, ...) {
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// s must be allocated
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
int sprintf(char* s, const char* format, ...) {
|
|
|
|
int res;
|
|
|
|
__require_allocated_array(s);
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
// requires stream to be allocated
|
|
|
|
int vfprintf(FILE* stream, const char* format, va_list arg) {
|
|
|
|
int res;
|
|
|
|
FILE tmp;
|
|
|
|
|
|
|
|
tmp = *stream;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
int vsprintf(char* s, const char* format, va_list arg) {
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
int vsnprintf(char* s, size_t n, const char* format, va_list arg) {
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic nonnegative integer
|
|
|
|
int vprintf(const char* format, va_list arg) {
|
|
|
|
int res;
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// forces path to be allocated
|
|
|
|
// return nondeterministically 0 or -1
|
|
|
|
int utimes(const char* path, const struct timeval times[2]) {
|
|
|
|
int success = __infer_nondet_int();
|
|
|
|
|
|
|
|
__require_allocated_array(path);
|
|
|
|
// return random result
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// forces filename to be allocated
|
|
|
|
// return nondeterministically 0 or -1
|
|
|
|
int unlink(const char* filename) {
|
|
|
|
int success = __infer_nondet_int();
|
|
|
|
__require_allocated_array(filename);
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return nondeterministically 0 or -1
|
|
|
|
int usleep(useconds_t useconds) {
|
|
|
|
int success = __infer_nondet_int();
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dst and src must be allocated
|
|
|
|
// return an integer between 0 and size
|
|
|
|
size_t strlcpy(char* dst, const char* src, size_t size) {
|
|
|
|
int size_dst;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
|
|
|
|
// force src to be allocated
|
|
|
|
__require_allocated_array(src);
|
|
|
|
|
|
|
|
// force dst to be allocated for at least size
|
|
|
|
__require_allocated_array(dst);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_dst = __get_array_length(dst);
|
|
|
|
INFER_EXCLUDE_CONDITION(size > size_dst);
|
|
|
|
|
|
|
|
INFER_EXCLUDE_CONDITION(res > size || res < 0);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dst and src must be allocated
|
|
|
|
// return an integer between 0 and size
|
|
|
|
size_t strlcat(char* dst, const char* src, size_t size) {
|
|
|
|
int size_dst;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = __infer_nondet_int();
|
|
|
|
|
|
|
|
// force src to be allocated
|
|
|
|
__require_allocated_array(src);
|
|
|
|
|
|
|
|
// force dst to be allocated for at least size
|
|
|
|
__require_allocated_array(dst);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
size_dst = __get_array_length(dst);
|
|
|
|
INFER_EXCLUDE_CONDITION(size > size_dst);
|
|
|
|
|
|
|
|
INFER_EXCLUDE_CONDITION(res > size || res < 0);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// path must be allocated
|
|
|
|
// assign nonteterministically to the contents of buf
|
|
|
|
// return 0 or -1
|
|
|
|
int statfs(const char* path, struct statfs* buf) {
|
|
|
|
int success;
|
|
|
|
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
|
|
|
|
// force path to be allocated
|
|
|
|
__require_allocated_array(path);
|
|
|
|
|
|
|
|
struct statfs s; // uninitialized struct statfs
|
|
|
|
*buf = s;
|
|
|
|
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// path must be allocated
|
|
|
|
// assign nonteterministically to the contents of buf
|
|
|
|
// return 0 or -1
|
|
|
|
int stat(const char* path, struct stat* buf) {
|
|
|
|
int success;
|
|
|
|
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
|
|
|
|
// force path to be allocated
|
|
|
|
__require_allocated_array(path);
|
|
|
|
|
|
|
|
struct stat s; // uninitialized struct stat
|
|
|
|
*buf = s;
|
|
|
|
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int remove(const char* path) {
|
|
|
|
int success;
|
|
|
|
|
|
|
|
// force path to be allocated
|
|
|
|
__require_allocated_array(path);
|
|
|
|
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* readline(const char* prompt) {
|
|
|
|
char* ret;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
// force prompt to be allocated when not null
|
|
|
|
if (prompt != NULL) {
|
|
|
|
__require_allocated_array(prompt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// return random string of positive size
|
|
|
|
size = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(size < 0);
|
|
|
|
|
|
|
|
ret = (char*)malloc(sizeof(size));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
long random(void) {
|
|
|
|
long ret;
|
|
|
|
|
|
|
|
ret = __infer_nondet_long_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// requires stream to be allocated
|
|
|
|
int putc(int c, FILE* stream) {
|
|
|
|
int rand;
|
|
|
|
FILE tmp;
|
|
|
|
|
|
|
|
tmp = *stream;
|
|
|
|
rand = __infer_nondet_int();
|
|
|
|
if (rand > 0)
|
|
|
|
return c; // success
|
|
|
|
else
|
|
|
|
return EOF; // failure
|
|
|
|
}
|
|
|
|
|
|
|
|
int access(const char* path, int mode) {
|
|
|
|
int success;
|
|
|
|
|
|
|
|
// force path to be allocated
|
|
|
|
__require_allocated_array(path);
|
|
|
|
|
|
|
|
// determine return value
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
|
|
|
|
return (success > 0) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t confstr(int name, char* buf, size_t len) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
// determine return value
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < 0);
|
|
|
|
|
|
|
|
// buf should be allocated if len is not zero. Otherwise, we want buf=0.
|
|
|
|
if (len)
|
|
|
|
__require_allocated_array(buf);
|
|
|
|
else
|
|
|
|
INFER_EXCLUDE_CONDITION(buf != 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a non-deterministic value
|
|
|
|
// stream is not required to be allocated
|
|
|
|
int fflush(FILE* stream) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
int flock(int fd, int operation) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fsync(int fildes) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fsctl(const char* path,
|
|
|
|
unsigned long request,
|
|
|
|
void* data,
|
|
|
|
unsigned int options) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
// forces path and data to be allocated
|
|
|
|
__require_allocated_array(path);
|
|
|
|
__require_allocated_array(data);
|
|
|
|
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getrusage(int who, struct rusage* r_usage) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
INFER_EXCLUDE_CONDITION(r_usage == 0);
|
|
|
|
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#define gettimeofday_tzp_decl void* __restrict tzp
|
|
|
|
#else
|
|
|
|
#ifdef __CYGWIN__
|
|
|
|
#define gettimeofday_tzp_decl void* __restrict tzp
|
|
|
|
#else
|
|
|
|
#define gettimeofday_tzp_decl struct timezone* __restrict tzp
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int gettimeofday(struct timeval* __restrict tp, gettimeofday_tzp_decl) {
|
|
|
|
struct timeval tmp_tp;
|
|
|
|
struct timezone tmp_tzp;
|
|
|
|
int success;
|
|
|
|
|
|
|
|
if (tp != 0)
|
|
|
|
*tp = tmp_tp;
|
|
|
|
if (tzp != 0)
|
|
|
|
*(struct timezone*)tzp = tmp_tzp;
|
|
|
|
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
return success ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct tm* localtime_r(const time_t* __restrict timer,
|
|
|
|
struct tm* __restrict result) {
|
|
|
|
int success;
|
|
|
|
struct tm tmp;
|
|
|
|
|
|
|
|
INFER_EXCLUDE_CONDITION(timer == 0);
|
|
|
|
INFER_EXCLUDE_CONDITION(result == 0);
|
|
|
|
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
*result = tmp;
|
|
|
|
|
|
|
|
return (success > 0) ? result : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mkdir(const char* filename, mode_t mode) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
__require_allocated_array(filename);
|
|
|
|
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int munmap(void* addr, size_t len) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
INFER_EXCLUDE_CONDITION(addr == 0);
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutex_destroy(pthread_mutex_t* mutex) {
|
|
|
|
INFER_EXCLUDE_CONDITION(mutex == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutex_init(pthread_mutex_t* __restrict mutex,
|
|
|
|
const pthread_mutexattr_t* __restrict attr) {
|
|
|
|
INFER_EXCLUDE_CONDITION(mutex == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutex_lock(pthread_mutex_t* mutex) {
|
|
|
|
INFER_EXCLUDE_CONDITION(mutex == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutex_trylock(pthread_mutex_t* mutex) {
|
|
|
|
INFER_EXCLUDE_CONDITION(mutex == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutex_unlock(pthread_mutex_t* mutex) {
|
|
|
|
INFER_EXCLUDE_CONDITION(mutex == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr) {
|
|
|
|
INFER_EXCLUDE_CONDITION(attr == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutexattr_init(pthread_mutexattr_t* attr) {
|
|
|
|
INFER_EXCLUDE_CONDITION(attr == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value
|
|
|
|
int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type) {
|
|
|
|
INFER_EXCLUDE_CONDITION(attr == 0);
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns a nondeterministc value and forces type to be allocated and set its
|
|
|
|
// content
|
|
|
|
int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr, int* type) {
|
|
|
|
INFER_EXCLUDE_CONDITION(attr == 0);
|
|
|
|
*type = __infer_nondet_int();
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a positive non-deterministic number or -1.
|
|
|
|
// requires stream to be allocated
|
|
|
|
int fileno(FILE* stream) {
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret == 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fstat(int fildes, struct stat* buf) {
|
|
|
|
int ret;
|
|
|
|
struct stat s; // uninitialized struct stat
|
|
|
|
*buf = s;
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// treates as skyp. Return nondeterministically 0 or -1
|
|
|
|
int futimes(int fildes, const struct timeval times[2]) {
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef getchar // cygwin defines getchar as a macro
|
|
|
|
#undef getchar
|
|
|
|
#endif
|
|
|
|
int getchar(void) {
|
|
|
|
// randomly produce an error
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
if (ret < 0)
|
|
|
|
return EOF;
|
|
|
|
else
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int isatty(int fildes) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < 0 || ret > 1);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void perror(const char* s) {
|
|
|
|
__require_allocated_array(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pipe(int fildes[2]) {
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int raise(int sig) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
ssize_t read(int fildes, void* buf, size_t nbyte) {
|
|
|
|
if (nbyte == 0)
|
|
|
|
return 0;
|
|
|
|
__require_allocated_array(buf);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
INFER_EXCLUDE_CONDITION(__get_array_length(buf) < nbyte);
|
|
|
|
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > nbyte);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigaction(int sig, const struct sigaction* act, struct sigaction* oact) {
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || ret > 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the first argument
|
|
|
|
// long __builtin_expect(long x, long y) {
|
|
|
|
// return x;
|
|
|
|
//}
|
|
|
|
// TODO: this function has been disabled because it cannot be compiled with
|
|
|
|
// LLVM.
|
|
|
|
// It is normally a builtin that should not be implemented and LLVM complains
|
|
|
|
// about this
|
|
|
|
|
|
|
|
#ifdef clearerr // cygwin defines clearerr as a macro
|
|
|
|
#undef clearerr
|
|
|
|
#endif
|
|
|
|
// modelled as skip
|
|
|
|
// stream is required to be allocated
|
|
|
|
void clearerr(FILE* stream) {
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef ferror // cygwin defines ferror as a macro
|
|
|
|
#undef ferror
|
|
|
|
#endif
|
|
|
|
// return a nondeterministic value
|
|
|
|
// stream required to be allocated
|
|
|
|
int ferror(FILE* stream) {
|
|
|
|
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef feof // cygwin defines feof as a macro
|
|
|
|
#undef feof
|
|
|
|
#endif
|
|
|
|
// return a nondeterministic value
|
|
|
|
// stream required to be allocated
|
|
|
|
int feof(FILE* stream) {
|
|
|
|
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// write to *pos and return either 0 or -1
|
|
|
|
// stream is required to be allocated
|
|
|
|
int fgetpos(FILE* __restrict stream, fpos_t* __restrict pos) {
|
|
|
|
|
|
|
|
int success;
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
#ifdef __APPLE__ // fpos_t is a long in MacOS, but a struct in Linux.
|
|
|
|
*pos = __infer_nondet_long_int();
|
|
|
|
#else
|
|
|
|
pos->__pos = __infer_nondet_long_int();
|
|
|
|
#endif
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
if (success)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read from *pos and return either 0 or -1
|
|
|
|
// stream is required to be allocated
|
|
|
|
int fsetpos(FILE* stream, const fpos_t* pos) {
|
|
|
|
|
|
|
|
int success;
|
|
|
|
FILE tmp;
|
|
|
|
tmp = *stream;
|
|
|
|
fpos_t t;
|
|
|
|
t = *pos;
|
|
|
|
success = __infer_nondet_int();
|
|
|
|
if (success)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a value between 0 and nmemb
|
|
|
|
size_t fread(void* __restrict ptr,
|
|
|
|
size_t size,
|
|
|
|
size_t nmemb,
|
|
|
|
FILE* __restrict stream) {
|
|
|
|
size_t res;
|
|
|
|
res = __infer_nondet_size_t();
|
|
|
|
if (size == 0 || nmemb == 0)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0 || res > nmemb);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a value between 0 and nmemb
|
|
|
|
size_t fwrite(const void* __restrict ptr,
|
|
|
|
size_t size,
|
|
|
|
size_t nmemb,
|
|
|
|
FILE* __restrict stream) {
|
|
|
|
size_t res;
|
|
|
|
res = __infer_nondet_size_t();
|
|
|
|
if (size == 0 || nmemb == 0)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(res < 0 || res > nmemb);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t strcspn(const char* s1, const char* s2) {
|
|
|
|
__require_allocated_array(s1);
|
|
|
|
__require_allocated_array(s2);
|
|
|
|
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There is non-standard version of strerr_r:
|
|
|
|
// http://linux.die.net/man/3/strerror_r
|
|
|
|
// It's not modelled right now
|
|
|
|
#if defined __APPLE__ || (defined __USE_XOPEN2K && !defined __USE_GNU)
|
|
|
|
int strerror_r(int errnum, char* strerrbuf, size_t buflen) {
|
|
|
|
__require_allocated_array(strerrbuf);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
INFER_EXCLUDE_CONDITION(__get_array_length(strerrbuf) < buflen);
|
|
|
|
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ssize_t write(int fildes, const void* buf, size_t nbyte) {
|
|
|
|
__require_allocated_array(buf);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
INFER_EXCLUDE_CONDITION(__get_array_length(buf) < nbyte);
|
|
|
|
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || nbyte < ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int creat(const char* path, mode_t mode) {
|
|
|
|
__require_allocated_array(path);
|
|
|
|
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled as skip
|
|
|
|
int fcntl(int fildes, int cmd, ...) {
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modelled as skip
|
|
|
|
int sigprocmask(int how, const sigset_t* set, sigset_t* oset) {
|
|
|
|
int ret = __infer_nondet_int();
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < -1 || 0 < ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// modelled as skip
|
|
|
|
void setbuf(FILE* __restrict stream, char* __restrict buf) {}
|
|
|
|
|
|
|
|
// return nondeterministically 0 or EOF
|
|
|
|
int setvbuf(FILE* __restrict stream,
|
|
|
|
char* __restrict buf,
|
|
|
|
int mode,
|
|
|
|
size_t size) {
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = __infer_nondet_int();
|
|
|
|
if (n)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the array base must be allocated with at least nmemb elements
|
|
|
|
// nondeterministically return 0 or a pointer inside the array
|
|
|
|
void* bsearch(const void* key,
|
|
|
|
const void* base,
|
|
|
|
size_t nmemb,
|
|
|
|
size_t size,
|
|
|
|
int (*compar)(const void*, const void*)) {
|
|
|
|
int base_size;
|
|
|
|
int nondet;
|
|
|
|
int offset;
|
|
|
|
nondet = __infer_nondet_int();
|
|
|
|
offset = __infer_nondet_int();
|
|
|
|
__require_allocated_array(base);
|
Optimize normalization, substitution, renaming of array types
Summary:
Array types where the length is not statically known were represented
using fresh variables. This diff:
- Makes array type length optional, reducing the amount of work needed
for renaming, substitution, and normalization.
- Revises uses of array length so that the length component of a
Tarray type represents only the statically determined constant
length of an array type, and the length component of a Sizeof
expression represents the dynamically determined length of an array
value.
- Restricts the type of static lengths from a general expression
(Sil.exp) to an integer (Sil.Int.t), enforcing that static types are
constant. This in particular ensures that types contain no
variables, and so are invariant under operations such as renaming
and substitution.
- Removes the type substitution and renaming functions typ_sub,
typ_normalize, and typ_captured_ren. Now that array type lengths
are constant integers, all of these functions are the identity.
Reviewed By: cristianoc
Differential Revision: D3387343
fbshipit-source-id: b5db768
9 years ago
|
|
|
base_size = __get_array_length(base);
|
|
|
|
INFER_EXCLUDE_CONDITION(nmemb > base_size);
|
|
|
|
if (nondet)
|
|
|
|
return 0;
|
|
|
|
INFER_EXCLUDE_CONDITION(offset < 0 || offset >= nmemb);
|
|
|
|
return (char*)base + offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
int mblen(const char* s, size_t n) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n) {
|
|
|
|
return (size_t)__infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n) {
|
|
|
|
return __infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// modeled as skip
|
|
|
|
void qsort(void* base,
|
|
|
|
size_t nmemb,
|
|
|
|
size_t size,
|
|
|
|
int (*compar)(const void*, const void*)) {}
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
int strcoll(const char* s1, const char* s2) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n) {
|
|
|
|
return (size_t)__infer_nondet_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a nondeterministic value
|
|
|
|
int wctomb(char* s, wchar_t wc) { return __infer_nondet_int(); }
|
|
|
|
|
|
|
|
// modeled like open
|
|
|
|
int socket(int namespace_, int style, int protocol) {
|
|
|
|
int* ret = (int*)malloc(sizeof(int));
|
|
|
|
if (ret) {
|
|
|
|
__set_file_attribute(ret);
|
|
|
|
INFER_EXCLUDE_CONDITION(ret < (int*)1); // force result to be > 0
|
|
|
|
return (size_t)ret;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* xcalloc(size_t nmemb, size_t size) {
|
|
|
|
void* ret = calloc(nmemb, size);
|
|
|
|
INFER_EXCLUDE_CONDITION(ret == NULL);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* xmalloc(size_t size) {
|
|
|
|
void* ret = malloc(size);
|
|
|
|
INFER_EXCLUDE_CONDITION(ret == NULL);
|
|
|
|
return ret;
|
|
|
|
}
|