search a struct in C - c

void search(struct _data *BlackBox, char *name, int size) - this function
will get the dynamic array of struct passed to it, the name we are looking
for, and the size of the array. This function will then search the dynamic
array for the name.
typedef struct _data
{
char* name;
long number;
} _data;
int scan(FILE *(*stream));
struct _data *load(FILE *stream, int size);
void search(struct _data *Blackbox, char *name, int size);
int main()
{
int size = scan(&stream);
rewind(stream);
_data *data = load(stream, size);
char input;
printf("Please Input Search Name: ");
scanf("%s", input);
while (input != NULL)
{
search(data, input, size);
}
}
void search(struct _data *Blackbox, char *name, int size)
{
for (int i=0; i<size; i++)
{
if (strcmp(name,Blackbox[i].name) != 0)
{
printf("Success");
}
else
{
printf("Name Not Found");
}
}
}
But I am getting the following output
Output:
LINES: 2
ron 7774013
jon 7774014
Please Input Search Name: ron
RUN FINISHED; Segmentation fault: 11; real time: 2s; user: 0ms; system: 0ms

In your main function you have "char input;", and "scanf("%s",input);". That's wrong, because the %s specifies a string parameter, but input is a char variable. So whatever is typed in by the user is stored at some random place in memory.
Change the declaration of input to something lime "char input[1000];". And you'll have to do something about your while loop too.

You need to declare the search function before you try to use it.
The compiler should even warn you about that implicit declaration.

If you get a segmentation fault then one the following applies:
Your struct Blackbox in search function is not pointing to a valid memory location and thus the Blackbox[i] produces the fault
The name member of the struct is not pointing to a valid memory location and thus the Blackbox[i].name is producing the fault
The size of the Blackbox array is less than size-1.
To do this, use a debugger and check the Blackbox where is pointing. Then check the Blackbox.name where is pointing. Then, check if there is anything to the Blackbox array up to size-1. I assume that either will be null. Perhaps an error in the assignment of the load function or a wrong usage of the size.

Related

C: sha256 hash function outputs in fields of structure array inducing crash when writing structure contents to disk

I am attempting to write a program which will store credential information in an array of structures and then print that information out into a file (this is for learning purposes only, don't worry). To do this, I create an array of structures and then raster through that array to assign the pertinent information to each field. This proceeds without issue. I then attempt to raster through the array again to write each structure's fields to a file whereupon the program crashes after the first write (ie only one structure's worth of content is successfully written to the output file).
I created the following simplified / stripped down variant of my program which reproduces the error. I believe the problem lies within the set_hash_entry function as the error only manifested after that function was re-introduced into my stripped down code in place of a hard coded test value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/sha.h"
#include <time.h>
#include <math.h>
struct password_struct {
char password[17];
char hash[65];
float entropy;
};
struct password_struct* allocate_heap_memory(int num_passwords);
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs);
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs);
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs);
void set_hash_entry(struct password_struct* user_password_structs);
int main(void) {
int num_passwords = 2;
struct password_struct* user_password_structs = allocate_heap_memory(num_passwords);
struct password_struct* allocated_memory_start_ptr = user_password_structs;
orchestrate_value_setting(num_passwords, user_password_structs);
user_password_structs = allocated_memory_start_ptr; // Resetting pointer to allow cycling back through all structures for appending data to output file
orchestrate_file_output(num_passwords, user_password_structs);
free(allocated_memory_start_ptr);
}
struct password_struct* allocate_heap_memory(int num_passwords) {
struct password_struct* user_password_structs = malloc(num_passwords * sizeof(struct password_struct));
if (!user_password_structs) {
printf("Malloc failed, exiting\n");
exit(0);
}
return user_password_structs;
}
void set_hash_entry(struct password_struct* user_password_structs){
int pass_entry_length = strlen(user_password_structs->password);
SHA256_CTX context;
unsigned char generated_hash[65]; //sha256 standard digest length + 1;
SHA256_Init(&context);
SHA256_Update(&context, (unsigned char *)user_password_structs->password, pass_entry_length);
SHA256_Final(generated_hash, &context);
char* hash_ptr = &user_password_structs->hash[0];
int i;
for (i=0; i < (64); i++) {
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}
user_password_structs->hash[64] = '\0';
printf("%s\n", user_password_structs->hash);
}
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs) {
char pw1[10] = "test";
char pw2[10] = "test2";
float entropy1 = 5.0;
float entropy2 = 10.0;
strcpy(user_password_structs->password, pw1);
set_hash_entry(user_password_structs);
user_password_structs->entropy = entropy1;
user_password_structs++;
strcpy(user_password_structs->password, pw2);
set_hash_entry(user_password_structs);
user_password_structs->entropy = entropy2;
user_password_structs++;
}
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs) {
printf("Writing data to disk...\n");
char file_name[20] = "name";
int i;
for (i = 0; i < num_passwords; i++) {
write_results_to_disk(file_name, user_password_structs);
user_password_structs++;
}
}
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs) {
FILE *file_pointer = fopen(file_name, "a");
if (file_pointer == NULL) {
printf("Error: Failed to open file\n");
exit(1);
}
fprintf(file_pointer, "%s:%s:%f\n", user_password_structs->password, user_password_structs->hash, user_password_structs->entropy);
fclose(file_pointer);
}
After running this program, the following output is produced:
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
Writing data to disk...
*** Error in `./diagnostic': free(): invalid next size (normal): 0x0804b0c0 ***
Aborted (core dumped)
I naively assumed this was an overflow issue related to my
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]);
operation, but increasing the size of the hash buffer in the struct does not seem to help. Any help would be greatly appreciated!
I compiled as follows: gcc -o diagnostic -g diagnostic.c -lcrypto -lm
char hash[65];
Okay, hash has room for 65 characters.
char* hash_ptr = &user_password_structs->hash[0];
So, hash_ptr points to hash, so it points to room for 65 characters.
for (i=0; i < (64); i++) {
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}
When i is 60, i*2 is 120. So you're trying to write to the 120th position of a buffer with room for 65 characters.
Change that (64) to 32 in the loop or change hash[65] to a bigger buffer.
Using valgrind found this immediately. You should learn to use some too that detects buffer overflows, use after free, double frees, and similar problems.

Store getcwd on a struct on a function

typedef struct
{
char Path[100];
} DirectoryInformation;
void Getskelutofdirectorie(char * dir, int lvl)
{
DirectoryInformation DI[100];
char cwd[1024];
//Search recursive
// where I want to put the path on the struct to use on main
getcwd(cwd, sizeof(cwd));
strcpy(DI[0].Path, cwd);
}
int main(void)
{
DirecoryInformation DI[100];
printf("%s", DI[0].Path);
}
I can print the path but if i use on main function will work.
Can somebody help me out?
It executes without error but when I print out make segmentation fault
Your code invokes undefined behavior by using value of variable DI having automatic storage duration and not initialized, which is indeterminate.
Call the function with passing pointer to the struct to store the data, then store there.
typedef struct
{
char Path[100];
} DirectoryInformation;
void Getskelutofdirectorie(DirectoryInformation * DI, char * dir, int lvl)
{
char cwd[100]; // cwd was too long, so there was risk of buffer overrun when copying
//Search recursive
//where i want to put the path on the struct to use on main
getcwd(cwd, sizeof(cwd));
strcpy(DI[0].Path, cwd);
}
int main(void)
{
DirectoryInformation DI[100] = {{""}}; // initialize for in case the function fails to set values
Getskelutofdirectorie(DI, NULL, 0); // pass proper parameter
printf("%s", DI[0].Path);
}

C program football team structure with pointer elements and dynamic allocation

I have a question about passing function to another function which both have structure as arguments. First I created two structures:
typedef struct
{
char name[25],surname[25];int number;
}PLAYER;
typedef struct
{
char nameofteam[25];int numberofplayers;char *players;
}TEAM;
Then I defined a function to read elements of one player:
void readplayer(PLAYER *);
void readplayer(PLAYER *pi)
{
printf("name:");scanf("%s",pi->name);
printf("surname:");scanf("%s",pi->surname);
printf("number of player:");scanf("%d",&pi->number);
}
My question is how to create function which prototype is void readteam(TEAM*) which will read data for one team, but using function readplayer and call it in main()? Here is what I have tried:
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
char name[25],surname[25];int number;
}PLAYER;
typedef struct
{
char nameofteam[25];int numberofplayers;char *players;
}TEAM;
void readplayer(PLAYER *pi)
{
printf("name:");scanf("%s",pi->name);
printf("surname:");scanf("%s",pi->surname);
printf("number of player:");scanf("%d",&pi->number);
}
void readteam(TEAM *pt)
{
char players[101];int i;
printf("name of team:");scanf("%s",pt->nameofteam);
printf("number of players in team:");scanf("%d",&pt->numberofplayers);
printf("players:");scanf("%s",players);
pt->players=(char *)calloc(length(players)+1,sizeof(char));
copy(pt->players,players);
for(i=0;i<pt->numberofplayers;i++)
{
printf("%d.",i+1);
readplayer(pt+i);
}
}
void erase(TEAM *);
void erase(TEAM *pt)
{
free(pt->players);
}
int length(char *s)
{
int d=-1;
while(s[++d]);
return d;
}
void copy(char *s1,char *s2)
{
while(*s1++ = *s2++);
}
int main()
{
int i,n;
TEAM *p;
do
{
printf("n=");scanf("%d",&n);
}
while(n<1);
p=(TEAM *)malloc(n * sizeof(TEAM));
for(i=0;i<n;i++)
{
printf("%d.",i+1);readteam(p+i);
}
free(p);
}
This gives me an error at the last input (in compiling, not debugging). Must be because of inappropriate use of dynamic allocation. I didn't use <string.h library. Obviously, only the readteam function has to be in main().
Thanks for the answers.
You are confused on how to store the playsrs. You have created a PLAYER struct, but you never use it. Instead, you insist that players must be a single string.
But it should work like this: You have n teams. Ecah team has m players. All team info is stored in your ´TEAMstruct. All player info is stored in yourPLAYERstruct. Because a team is made up of players, there should be aPLAYER` entry in your struct:
typedef struct {
char name[25];
char surname[25];
int number;
} PLAYER;
typedef struct {
char nameofteam[25];
int numberofplayers;
PLAYER *players;
} TEAM;
Then, when you read players, you read the bare team info in readteam. But you don't read anything about individual players there, because you delegate that to readplayer. Of course, the pointer you pass to that function must be that for a player, not one for a team:
void readplayer(PLAYER * pi)
{
printf("name:");
scanf("%s", pi->name);
printf("surname:");
scanf("%s", pi->surname);
printf("number of player:");
scanf("%d", &pi->number);
}
void readteam(TEAM * pt)
{
int i;
printf("name of team:");
scanf("%s", pt->nameofteam);
printf("number of players in team:");
scanf("%d", &pt->numberofplayers);
pt->players = calloc(pt->numberofplayers, sizeof(*pt->players));
for (i = 0; i < pt->numberofplayers; i++) {
printf("Player %d:\n", i + 1);
readplayer(pt->players + i);
}
}
Your cast to (char *) hides the warning about incompatible types. You should cast only when you know what you're doing. In this simple program, you don't need casts.
In your original code, there are warnings about "implicit declarations". These concern your copy and length functions. (By the way, what's wrong with strlen and strcpy?) You should move these functions to the top so that they are declared before they are called. ALternatively, provide prototypes at the beginning of your code or in a header file, which you #include at the top. (But now that you read into PLAYER structs, these functions are no longer needed.)

Program with array of structs crashes

I have an array with multiple structs. When i ask the user to enter data the first time everything works but when i ask again for the next position in the array the program crashes. If this method doesn't work souldn't the program crash in the beginning? Is something wrong with malloc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
void init(int n)
{
stack = malloc(n);
}
int push(struct student_or_prof **pinx,int *head,int n)
{
char name[50];
printf("\nn= %d\n",n);
printf("\nhead= %d\n",*head);
if(*head==n)
{
printf("Stack is full.\n");
return 1;
}
char x;
printf("Student or Professor? [s/p] ");
getchar() != '\n';
scanf("%c",&x);
if(x=='s')
{
getchar() != '\n';
pinx[*head]->flag = 0;
printf("\n\nGive student's name: ");
fgets(pinx[*head]->student.name,sizeof(pinx[*head]->student.name),stdin);
printf("\nGive student's semester: ");
scanf("%d",&(pinx[*head]->student.semester));
printf("\nName = %s\tSemester = %d",pinx[*head]->student.name,pinx[*head]->student.semester);
}
else if(x=='p')
{
getchar() != '\n';
pinx[*head]->flag = 1;
printf("\n\nGive professor's name: ");
fgets(pinx[*head]->prof.name,sizeof(pinx[*head]->prof.name),stdin);
printf("\nGive course: ");
fgets(pinx[*head]->prof.course,sizeof(pinx[*head]->prof.course),stdin);
printf("\nName = %s\tCourse = %s\n",pinx[*head]->prof.name,pinx[*head]->prof.course);
}
(*head)++;
printf("\nhead= %d\n",*head);
}
int main()
{
int n,i;
printf("Give size: ");
scanf("%d",&n);
init(n);
for(i=0;i<n;i++)
push(&stack,&exp1.head,n);
return 0;
}
You need to malloc the structure not n
malloc(sizeof(struct student_or_prof)*n)
EDIT:
And your code crashes again because pinx is a double pointer, so this operation is not valid:
pinx[*head]->flag = 0;
this is equivalent to:
*(pinx + *head)->flag = 0;
Since you are not changing what stack points to, you are better off using a single pointer instead of a double pointer.
So instead you should change your push API:
int push(struct student_or_prof *pinx,int *head,int n)
and call it like:
push(stack,&exp1.head,n);
malloc allocates the given number of bytes.
You have to multiply n with the size of your struct, to allocate enough memory.
pinx does not point to an array, so pinx[*head] is going to access invalid memory unless *head is zero.
I think you meant (*pinx)[*head] , which accesses the N-th element of the array you allocated via malloc. For example (*pinx)[*head].prof.name etc.
BTW, your head number doesn't seem to be used at all, except for exp1.head, maybe it'd be better to remove head from the struct, and just have a single variable head?

accessing the array inside array of structures

I have a structure as follows
struct a
{
char* ap;
char* inputs[10];
int e;
};
then I have created an array of this structure like struct a list [100];
now i want to fille the array inputs[10] and for that I am using the syntax to access the first location :
ip=0;
inp=0;
list[ip].inputs[inp]
but I am gettin the error "error C2107: illegal index, indirection not allowed" on compiling the code
please suggest how to access the array location inside array of structure.
regards
priya
Here you use array of character pointer in your structure. So Initially you allocate memory for you structure by creation list of 100. I think you didn't create memory for you array of character pointer. You have to create memory for each of character pointer. So I suggest example code.
#include <stdio.h>
struct a
{
char* ap;
char* inputs[10];
int e;
};
int main()
{
int ip=0;
int inp=0;
struct a list[100];
list[ip].inputs[inp]= (char*)malloc(25);
scanf("%s",list[ip].inputs[inp]);//Or other copy function to fill string
printf("output %s",list[ip].inputs[inp]);
}
Working fine on my pc.. here is my code..
#include <stdio.h>
struct a
{
char* ap;
char* inputs[10];
int e;
};
int main()
{
int ip=0;
int inp=0;
struct a list[100];
list[ip].inputs[inp] = 'A';
printf("This: %c", list[ip].inputs[ip]);
return 0;
}
OUTPUT= This: A
let me know whether it helped or not..
The struct themselves do not have data. You need to create objects of the struct type and set the objects ...
struct a
{
char* ap;
char* inputs[10];
int e;
};
/* I like to separate the type definition from the object creation */
struct a list [3];
list [0].inputs[0] = "Choclate";
list [0].inputs[1] = "Almond";
list [0].inputs[2] = "Rasberry";
Hope it ll usefull. Also refer this article

Resources