How to get Data & Control Dependency Slice using Frama-c - c

I was trying to do two things
Get a dynamic backward slice based on a criteria.
Map the slices statements back to the actual source code.
Problem 1: The slice returned by Frama-C doesn't return the exact statements that were relevant for the criteria - mainly the if and else statements.
Problem 2: How do I map the slicing statements back to the source code? The program gets changed when slicing (for example : int a=9 becomes 2 statements in sliced code int a; and a = 9;.) I am ok with the slice but what is the information I can use to map these back to the statements in the source code.
This is the source code.
void main(){
int ip1 = 9;
int ip2 = 3;
int option = 1;
int result = math(option,ip1,ip2);
//# slice pragma expr ((option == 1) || !(result == (ip1+ip2)));
}
int math(int option, int a, int b){
int answer = 0;
if (option == 1){
answer = a+b;
}else{
if (option == 2) {
answer = a-b;
}else { // a ^ b
for(int i=0 ;i<b; i++){
answer=answer*a;
}
}
}
return answer;
}
I use the following command to get the slice.
frama-c t.c -slicing-level 3 -slice-pragma main -slice-print
The slice I get from frama-c is :
void main(void)
{
int ip1;
int ip2;
int option;
int result;
ip1 = 9;
ip2 = 3;
option = 1;
result = math_slice_1(ip1,ip2);
/*# slice pragma expr option≡1∨!(result≡ip1+ip2); */ ;
return;
}
int math_slice_1(int a, int b)
{
int answer;
answer = a + b;
return answer;
}
Problem 1:
I dont get the if and else conditions in the slice. What should I do to get them?
I expected the following slice:
int math_slice_1(int a, int b)
{
int answer;
if (option == 1){
answer = a + b;
}
return answer;
}
Problem 2:
Source code has : int ip1 = 9;
But the sliced code has :
int ip1;
ip1 = 9;
How to map these 2 sliced statements back to the source code statement.

For Problem 1, the test is sliced out because it is always true since option is set to 1 in the main function. If you want to keep the test, you have to make option an entry (either external global variable or a parameter of main for instance), but then, there will be nothing to slice in the math function... The slicing tries to keep only what is strictly necessary, and the test is not in your case.

Related

A function in C runs for a set of values but gives Segmentation Fault: 11 for another

I am trying to find unique non-zero intersection between two sets. I have written a program which works for some set of arrays but gives segmentation fault for some. I have been trying to figure out why but have failed, any help will be greatly valued. The thing is the functions defined (NoRep and ComEle) are working fine but are unable to return the value to the assigned pointer in the case when Seg Fault is shown. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check complete\n");
// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check complete\n");
}
//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
// Have to remove repeating elements.
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:\t%d\n", CE[i]);}
printf("ComEle: %p\n",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];
}
}
NR[0] = cnt; // First element: # of relevant elements.
printf("NoRep: %p\n",NR);
return(NR);
}
Thanks again for your help!
Take a look at this code:
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
Here you have nested loops, i.e. a for-loop with a while-loop inside. So - in worst case - how many times can cnt1 be incremented?
The answer is size_ar1 * size_ar2
But your code only reserve size_ar1 + size_ar2 element for CE1. So you may end up writing outside the array.
You can see this very easy by printing cnt1 inside the loop.
In other words - your CE1 is too small. It should be:
int temp1 = size_ar1*size_ar2; // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
But be careful here - if the input arrays are big, the VLA gets huge and you may run in to stack overflow. Consider dynamic memory allocation instead of an array.
Besides the accepted answer: I have been missing a break statement in the while loop in ComEle function. It was not giving me the expected value of cnt1. The following will be the correct way to do it:
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}
This will also do away with the requirement for a bigger array or dynamic allocation as suggested (and rightly so) by #4386427

How to generate a new function in C?

I want a function that could take input a single integer from the user with validation, lets call it input_single_int. Such a function would greatly simplify my code. If a user gives incorrect input, then the function should show error and again prompt the user to fill out the correct input. The problem is the validation part, different inputs require different validation. Even if I send a validation function, how do I send the different parameters required by the validation function through input_single_int?
I want this function to be generic, so that I could use it multiple places. In the code given, if I add a parameter in input_single_int to accomodate input of variable b, I would have to change check_a function also, which I don't want to do. I also don't want to use global variables.
The only way which I could think of achieving this is through a function that could generate another function. Something like this:
func generate_check_b(int a) {
return int check_b(int b) { return (b > 0 && b < a); };
}
Is such a thing possible in C?
#define MM_SHOW 8
#define MM_QUIT 9
int input_single_int(int *var, char msg[], int exit_on_eq, int secondary_check(int val)) {
int inp_status, error, temp;
char skip;
do {
error = 0;
printf("%s", msg);
inp_status = scanf("%d", &temp);
if (inp_status != 1) {
error = 1;
do {
scanf("%c", &skip);
if (exit_on_eq) {
if (skip == 'e') {
system("clear");
return MM_SHOW;
} else if (skip == 'q') {
system("clear");
return MM_QUIT;
}
}
} while (skip != '\n');
}
if (!secondary_check(temp)) {
error = 1;
}
} while (error && printf("Please give a correct input.\n"));
*var = temp;
return 0;
}
int check_a(int a) { return a > 0;}
int check_b(int b, int a) { return (b > 0 && b < a);}
int main() {
int a, b;
char amsg[] = "a should be more than 0: ";
char bmsg[] = "b should be more than 0 and less than a: ";
input_single_int(&a, amsg, 1, check_a);
input_single_int(&b, bmsg, 1, check_b);
return 0;
}
A common idiom is a pair of parameters; a function and an opaque context pointer; so a simple case could be something like:
int check_range(int a, void *p) {
int *range = p;
return a >= range[0] && a < range[1];
}
struct Set { int n; int *vals; };
int check_set(int b, void *p) {
struct Set *s = p;
int i;
for (i = 0; i < s->n && s->vals[i] != b; i++) {}
return i < s->n;
}
If you look at the blocks extension to C supported by clang & gcc, it isn't far different from this, except that it is more sugary and has some really scary side effects.

Segmentation error in DFS

I have written a simple recursion procedure for DFS.
#include <stdbool.h>
void mydfs(int ROWS, int COLS,char **A,int row, int col, bool **visited){
static int rowAdjacencyParams[4] = {-1,0,1,0};
static int colAdjacencyParams[4] = {0,1,0,-1};
*(*(visited+col)+row) = true;
//visited[row][col] = true;
int i,newR,newC;
for(i = 0;i<4;i++){
newR = row + rowAdjacencyParams[i];
newC = col + colAdjacencyParams[i];
if(((newR >=0) && (newR < ROWS)) && ((newC>=0) && (newC < COLS))){
/*if((A[newR][newC] == 'X') && !visited[newR][newC]){
mydfs(ROWS,COLS,A,newR,newC,visited);
}*/
}
}
}
int black(char** A, int n1) {
int i,j,count = 0;
int cols = strlen(A[0]);
bool visited[n1][cols];
memset(visited,0,sizeof(visited));
for(i = 0;i<n1;i++){
for(j = 0;j<cols;j++){
if((A[i][j] == 'X') && !visited[i][j]){
count++;
mydfs(n1,cols,A,i,j,visited);
}
}
}
return count;
}
int main(){
int ROWS = 3;
int COLS = 7;
char P[ROWS][COLS]= {"OOOXOOO","OOXXOXO","OXOOOXO"};
printf("Number of islands = %d",black(P,COLS));
return 0;
}
UPDATED main Function
However, when I run this it gives me a segmentation fault for line visited[row][col] = true;. Then I tried to change it to *(*(visited+col)+row) = true; but still having the same segmentation fault error. Please explain why am I getting this error.
In addition to the character data exceeding the array's buffer as pointed out by the comments, beyond that another error is this:
int black(char** A, int n1) {
//...
for(i = 0;i<n1;i++){
for(j = 0;j<cols;j++){
if((A[i][j] == 'X') && !visited[i][j]){ /* A[i] is out of bounds */
The n1 is passed in as the number of columns, which is 7. However if you go back to main, you have this:
int ROWS = 3;
int COLS = 7;
char P[ROWS][COLS]= {"OOOXOOO","OOXXOXO","OXOOOXO"};
printf("Number of islands = %d",black(P,COLS));
The P array has only 3 rows. So when the black function is called, it is assuming that P has 7 rows, not 3 rows. This results in the A array accessing A[0], A[1], A[2], (good), but then A[3], etc. which is undefined behavior (and in your case, a crash).
So you need to get your column / row logic corrected.
I will let you in on a secret. Since you originally tagged your question as C++, I took the time to change those double stars to std::vector, and use the at() function to locate the issue. I know that you've now tagged your question as C99, but I would just like to be aware why tags are important. I don't know if C99 has this feature of auto-detecting boundary conditions like this.

how to initialize array of unknown size in c

I am doing a homework assignment for an intro to programming class in c.
I need to write a program that looks at an int array of unknown size (we are given a initializer list as the test case to use), and determine all the duplicates in the array.
To make sure that an element that was already found to be a duplicate doesn't get tested, I want to use a parallel array to the original that would hold the numbers of all the elements that were duplicates.
I need this array to be the same size as the original array, which of course we don't really know till the initializer list is given to us.
I tried using sizeof() to achieve this, but visual studio says that is an error due to the variable size (const int size = sizeof(array1);) not being constant. Am I not using sizeof correctly? Or is this logic flawed?
Perhaps there is another way to approach this, but I have yet to come up with one.
Here is the code included below, hope the comments don't make it too hard to read.
// Dean Davis
// Cs 1325
// Dr. Paulk
// Duplicates hw
#include <stdio.h>
int main()
{
int array1[] = { 0,0,0,0,123,124,125,3000,3000,82,876,986,345,1990,2367,98,2,444,993,635,283,544, 923,18,543,777,234,549,864,39,97,986,986,1,2999,473,776,9,23,397,15,822,1927,1438,1937,1956,7, 29,- 1 };
const int size = sizeof(array1);
int holdelements[size];
int a = 0; // counter for the loop to initialize the hold elements array
int b = 0; // counter used to move through array1 and be the element number of the element being tested
int c = 0; // counter used to move through holdelements and check to see if the element b has already been tested or found as duplicates
int d = 0; // counter used to move through array1 and check to see if there are any duplicates
int e = 0; // counter used to hold place in hold element at the next element where a new element number would go. sorry if that makes no sense
int flag = 0; // used as a boolian to make sure then large while loop ends when we reach a negative one value.
int flag2 = 0; // used as a boolian to stop the second while loop from being infinite. stops the loop when the end of hold elements has been reached
int flag3 = 0; // used to close the third while loop; is a boolian
int numberofduplicates=0;// keeps track of the number of duplicates found
for (a; a < size; a++)
{
if (a == (size - 1))
holdelements[a] = -1;
else
holdelements[a] = -2;
}
while (!flag)
{
flag2 = 0;
flag3 = 0;
if (array1[b] == -1)
flag = 1;
else
{
while ((!flag) && (!flag2))
{
if (holdelements[c] == -1)
flag2 = 1;
else if (array1[b] == holdelements[c])
{
b++;
c = 0;
if (array1[b] == -1)
flag = 1;
}
}
while (!flag3)
{
if (array1[d] == -1)
flag3 = 1;
else if (array1[b] == array1[d] && b != d)
{
printf("Duplicate of %d, index %d, was found at index %d.\n", array1[b], b, d);
holdelements[e] = d;
d++;
e++;
numberofduplicates++;
}
}
}
b++;
}
printf("Total Duplicates Found: %d\n", numberofduplicates);
return 0;
}
redo to the following:
const int size = sizeof(array1)/sizeof(int);

Why use this method of function pointers [duplicate]

This question already has answers here:
What are function pointers used for, and how would I use them?
(9 answers)
Closed 8 years ago.
Yesterday I learned of this really cool way to use function pointers.
Although I think its a really cool thing to be able to do I cant see WHY and WHERE this sort of method will be used?
Could someone shed some light on this?
int Mul(int x , int y)
{
return x*y;
}
int Div(int x , int y)
{ return x/y;
}
typedef int (*FuncP)(int,int);
int compu(FuncP functionP, int x , int y)
{return functionP(x , y)}
//Calling it will look like
compu(Mul,5,10);
Thanks
Cart
If you need something to be dynamic based on a situation like so:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
typedef int (*worker_operation)(int);
int check_for_new_woot(int inVal) {
int ret = arc4random() % 10;
if (ret < 5) {
puts("Found new woot!");
sleep(1);
return 1;
} else {
puts("No new woot :(");
sleep(1);
return 0;
}
}
int buy_current_woot(int inVal) {
if (inVal != 0) {
fprintf(stderr, "Insufficient funds!!!\n");
}
return 0;
}
int check_if_should_buy_woot(int inVal) {
printf("Should we buy the latest woot? ");
char input[10];
read(STDIN_FILENO, input, 10);
if (input[0] == 'y') {
return 1;
} else {
return 0;
}
}
void *worker_thread(void *inVal) {
worker_operation *ops = (worker_operation *)inVal;
int i = 0;
worker_operation op = ops[i];
int arg = 0;
while (op) {
arg = op(arg);
op = ops[++i];
}
free(ops);
return NULL;
}
pthread_t start_worker(worker_operation *ops) {
pthread_t pt;
pthread_create(&pt, NULL, worker_thread, ops);
return pt;
}
int main(int argc, const char *argv[]) {
bool autoBuy = true; // fetch whether we should automatically buy from woot.com from argv or stdin
int numberLoops = 10; // fetch number of times to loop through the process
int i;
worker_operation *operations;
if (autoBuy) {
operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 2 + 1));
for (i = 0; i < numberLoops; i++) {
operations[2 * i] = check_for_new_woot;
operations[2 * i + 1] = buy_current_woot;
}
operations[2 * i] = (worker_operation)NULL;
} else {
operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 3 + 1));
for (i = 0; i < numberLoops; i++) {
operations[3 * i] = check_for_new_woot;
operations[3 * i + 1] = check_if_should_buy_woot;
operations[3 * i + 2] = buy_current_woot;
}
operations[3 * i] = (worker_operation)NULL;
}
pthread_join(start_worker(operations), NULL);
return 0;
}
Note that in this code snippet uses function pointers in two places. We have a function which is agnostic of how the user wants the program to perform, that is start_worker simply creates a worker thread that will work with a list of operations. This can be easily used to create a program which has multiple threads going all with different operation queues. The second place function pointers are used are with threads. The ptrhead_create call uses a function pointer in order to create a new thread (the function specified is the function to be ran on the new thread).
Generally this is called a command programming paradigm. One can easily create an operation that another part of code can call, agnostic of what the function does. For instance this could be useful for games in the following situation:
We have a game controller that gives input. The user clicks 'up'. In code call the operation that is hooked to the 'up' action.
This modular approach allows one to enable settings for the controls so someone can hook a 'jump' operation to 'up' or a 'move forward' operation, or anything really.
Hope this helps!
Pointers to functions has multiple uses but, sticking to your example, pointer to funcions can help you to avoid hurge and ugly conditional branches like if's and switches:
If you create an associative array of operations characters as index and pointer to functions as value:
//implementacion in C doesn't matter for the example
operations["*"] = Mul;
operations["/"] = Div;
operations["*"] = Add;
operations["-"] = Sub;
You can do something like this:
int op1;
int op2;
char operation;
cout << "Insert first number /n";
cin >> op1;
cout << "Insert second number /n";
cin >> op2;
cout << "Insert operator /n";
cin >> operation;
cout >> compu(operations[operation],op1,op2);

Resources