Why is there an Invalid Write here (Valgrind) - c

I am coding a shell. When I execute it like this cat /dev/urandom | valgrind ./myshell to run some test and see if I don't have any segfault or other errors, valgrind sometimes tell me that I have an Invalid Write in function my_wordcpy at this line tab[++j] = str[*i];
It doesn't happen every time, but it does happen, and I just can't see why. Here is my code :
static int count_words(char *str, char *sep)
{
int quote;
int words;
int i;
i = -1;
if (count_quotes(str) == -1)
return (0);
words = 0;
quote = 0;
while (str[++i] != '\0')
{
if (str[i] == '"')
{
if (quote == 0)
quote = 1;
else
quote = 0;
}
if (quote == 0
&& (is_cinside(sep, str[i]) == 0 && str[i] != '\t' &&
(is_cinside(sep, str[i + 1]) == 1 ||
str[i + 1] == '\t' || str[i + 1] == '\0')))
++words;
}
return (words);
}
static int my_wordlen(char *str, int *i, char *sep)
{
int quote;
int j;
j = 0;
quote = 0;
while (str[++(*i)] != '\0')
if (str[*i] == '"' && quote == 0)
quote = 1;
else if (quote == 1 || (quote == 0 && is_cinside(sep, str[*i]) == 0 &&
str[*i] != '\t'))
{
++j;
if ((quote == 1 && str[*i + 1] == '"') ||
(quote == 0 && (is_cinside(sep, str[*i + 1]) == 1 ||
str[*i + 1] == '\t' ||
str[*i + 1] == '\0')))
{
if (quote == 1 && str[*i + 1] == '"')
++(*i);
return (j);
}
}
return (-1);
}
static char *my_wordcpy(char *tab, char *str, int *i, char *sep)
{
int quote;
int j;
j = -1;
quote = 0;
while (str[++(*i)] != '\0')
if (str[*i] == '"' && quote == 0)
quote = 1;
else if (quote == 1 || (quote == 0 &&
is_cinside(sep, str[*i]) == 0 && str[*i] != '\t'))
{
tab[++j] = str[*i]; /* here is the invalid write. */
if ((quote == 1 && str[*i + 1] == '"') ||
(quote == 0 && (is_cinside(sep, str[*i + 1]) == 1 ||
str[*i + 1] == '\t' || str[*i + 1] == '\0')))
{
if (quote == 1 && str[*i + 1] == '"')
++(*i);
tab[++j] = '\0';
return (tab);
}
}
return (NULL);
}
char **my_quotetowordtab(char *str, char *sep)
{
char **tab;
int words;
int i;
int j;
int k;
i = -1;
j = -1;
k = -1;
if (str == NULL)
return (NULL);
words = count_words(str, sep);
if ((tab = malloc(sizeof(char *) * (words + 1))) == NULL)
return (NULL);
while (++i < words)
{
if ((tab[i] = malloc(sizeof(char) * (my_wordlen(str, &j, sep) + 1)))
== NULL)
return (NULL);
tab[i] = my_wordcpy(tab[i], str, &k, sep);
}
tab[i] = NULL;
return (tab);
}

my_wordlen can return -1 and you don't check this before giving it to malloc. In this case 0 bytes are allocated hence in my_wordcopy a heap-buffer-overflow occurs.

What happens if you have a str with only a single or odd number of " quote characters? Seems like your code won't check for \0 in that case and therefore it could write passed the end of tab. I think you need to move your NUL character check outside of the 2nd if clause to catch both cases.

Related

error in finding no. of vowels in a string

//schecking no of vowels in a string.
#include <stdio.h>
#include <string.h>
void printstring();
int main() {
char sai[8]; //allows 8 charecters.
char a,e,j,o,u; //I have used j as i have already used i for iteration
fgets(sai, 8, stdin); //going to enter my name
char *ptr = sai; ///setting pointer for string
int i,t = 0;
for(i = 0;i <= 7; i++){
if(*(ptr+i) == a) || (*(ptr+i) == e) || (*(ptr+i) == j) || (*(ptr + i) == o) || (*(ptr + i) == u){
t = t+1;
}
else {
t = t;
}
}
printf("%d", t);
}
OUTPUT:
The compiler generated an error:
jill.c: In function 'main':
jill.c:12:23: error: expected expression before '||' token
if(*(ptr+i) == a) || (*(ptr+i) == e) || (*(ptr+i) == j) || (*(ptr + i) == o) || (*(ptr + i) == u){
^~
I expected the number of vowels as output, but an error has occured. Where am I going wrong?
Below listed points are incorrect in your code
Englobe the full condition between brackets in your if condition is missing
Single quotes are missing for character in your if statements. please go through here more explanation.
As comment from  Ted Lyngmo, Craig Estey a,e,j,o,u are uninitialized.
if (*(ptr + i) == a) ||(*(ptr + i) == e) || (*(ptr + i) == j) || (*(ptr + i) == o) || (*(ptr + i) == u)
changed to
if((ptr[i] == 'a') || (ptr[i] == 'e') || (ptr[i] == 'j') || (ptr[i] == 'o') || (ptr[i] == 'u'))
code
//schecking no of vowels in a string.
#include <stdio.h>
#include <string.h>
void printstring();
int main()
{
char sai[8];//allows 8 charecters.
char a,e,j,o,u; //I have used j as i have already used i for iteration
fgets(sai, 8, stdin); //going to enter my name
char *ptr = sai; ///setting pointer for string
int i,t = 0;
for(i = 0;i <= 7; i++)
{
if((ptr[i] == 'a') ||
(ptr[i] == 'e') ||
(ptr[i] == 'j') ||
(ptr[i] == 'o') ||
(ptr[i] == 'u'))
{
t = t+1;
}
else
{
t = t;
}
}
printf("%d", t);
}
Link for below Output:
apple
2

How to find unique word number of occurrences?

Can't figure out the bug in my code. Every time I input a sentence, the count does increment but the word adds the first letter of the previous word and increments one letter every time. How do I fix this?
void numberOfWordOccurrences(char str[MAX_CHAR]) {
int count = 0, i = 0, j = 0;
char uniqueToken[99][999];
int tokenCount[99] = {0};
while(str[i] != '\0') {
char token[999];
while(str[i] != ' ' && str[i] != '\0') {
token[j++] = str[i++];
}
if(token[j - 1] == ':' || token[j - 1] == ',' || token[j - 1] == '.' || token[j - 1] == ';' || token[j - 1] == '?' || token[j - 1] == '!') {
token[j - 1] = '\0';
}
//null
token[j] = '\0';
//flag
int flag = -1;
for(j = 0; j < count; j++) {
if(strcmp(uniqueToken[j], token) == 0) {
//if flag is valid, then...
flag = j;
tokenCount[flag] = token[flag] + 1;
break;
}
}
if(flag <= 1) {
tokenCount[count] = tokenCount[count] + 1;
strcpy(uniqueToken[count++], token);
}
i++;
}
}```
first you have to set j=0 inside of your main while loop ,otherwise when you go inside of this loop for(j = 0; j < count; j++) jwill in increase , so here token[j++] = str[i++]; you won't start to copy str in token from j=0 that is why you have previous words letters.
second I believe this condition if(flag <= 1) should be if(flag == -1) because if for example first and fifth word are similar flag would be 0 and again that string would be copied in uniqueToken.
also pay attention if you reach \0 you with your two i++ you will pass it and here while(str[i] != '\0') you won't check it so I suggest while(str[i-1] != '\0') also before sending string check if there is anything in it(in a case str[0]='\0'.
look
void numberOfWordOccurrences(char str[]) {
int count = 0, i = 0, j = 0;
char uniqueToken[99][999];
int tokenCount[99] = { 0 };
while (str[i-1] != '\0') {
j = 0;
char token[999];
while (str[i] != ' ' && str[i] != '\0') {
token[j++] = str[i++];
}
if (token[j - 1] == ':' || token[j - 1] == ',' || token[j - 1] == '.' || token[j - 1] == ';' || token[j - 1] == '?' || token[j - 1] == '!') {
token[j - 1] = '\0';
}
//null
token[j] = '\0';
//flag
int flag = -1;
for (j = 0; j < count; j++) {
if (strcmp(uniqueToken[j], token) == 0) {
//if flag is valid, then...
flag = j;
tokenCount[flag] = token[flag] + 1;
break;
}
}
if (flag == -1) {
tokenCount[count] = tokenCount[count] + 1;
strcpy(uniqueToken[count++], token);
strcpy(uniqueToken[count], "\0");
}
i++;
}
}

How to count matches?

Consedering 2 strings, I want to do a program in C that returns the number of possible matches between this 2 strings.
For example
$>./a.out "abc" "a*"
1
Because there is only 1 possible match : *="bc"
$>./a.out "abc" "a**"
3
Because there is only 3 possible matches : (*="bc", *="") ; (*="", *="bc") ; (*="b", *="c")
$>./a.out "ab cool ab cool ab" "ab*ab*"
2
Because there is 2 possible matches : (*=" cool ", *=" cool ab") ; (*=" cool ab cool ", *="")
I did a function "int match(char*, char*)" that returns true when there exists a match and false when there does not exist.
But i would like now to count the possible matches.
Any advices or suggestions?
int match(char* string, char* star) {
if (string[0] == '\0' && star[0] == '\0')
return 1;
else if (star[0] == '*')
return match(string, star+1);
else if (string[0] == '\0')
return 0;
else if (string[0] == star[0]){
if (star[-1] == '*') {
if (!match(string+1, star+1))
return match(string+1, star);
}
return match(string+1, star+1);
}
else if (string[0] != star[0] && star[-1] == '*')
return match(string+1, star);
else if (string[0] != star[0] && star[-1] != '*')
return 0;
}
int count_match(char* string, shar* star) {
int i;
for (i = 0; star[i] != '\0'; i += 1) {
if (star[i] != '*') {
if (star[i] != string[i])
return 0;
}
else {
int count = 0;
int j;
for (j = i; string[j] != '\0'; j += 1) {
count += count_match(string + j; star + i + 1);
count += count_match(string + j; star + i + 1);
return count;
}
}
return (string[i] == star[i]);
}

C split string function returns \377 at the end of string instead of \0. Why?

I tried to implement a small splitStringByString() function in C, this is how I have come so far:
char* splitStringByString(char* string, char* delimiter){
int i = 0, j = 0, k = 0;
while(*(string + i) != '\0'){
j = i;
while((*(string + j) == *(delimiter + k)) && (*(string + j) != '\0')){
if(*(delimiter + k + 1) == '\0'){
// return string from here.
char result[(strlen(string) - strlen(delimiter) + 1)]; // + 1 for '\0'
i = 0;
j++;
while(*(string + j) != '\0'){
result[i] = *(string + j);
i += 1;
j++;
}
i = (int)strlen(result);
result[i - 1] = '\0';
return result;
}
k++;
j++;
}
i++;
}
return NULL;
}
So it works more or less;
the function returns the string after the delimiter as wanted, but at the end of this string (the last character) is always \377.
I already found something that said this is an octal number or so (stackoverflow), but it is not very clear for me. Could you help me and give me some advice about what I did wrong?
Thanks a lot! :-)
I do not understand your code but to do what you mention in the comment
char *splitSstring(char *haystack, char *separator)
{
char *result = (haystack == NULL || separator == NULL || !strlen(haystack) || !strlen(separator)) ? NULL : haystack;
if (result != NULL)
{
result = strstr(haystack, separator);
if (result != NULL) result += strlen(separator);
}
return result;
}
or if you want to have it in the separate string
char *splitSstring(char *haystack, char *separator, char *res)
{
char *result = (haystack == NULL || separator == NULL || !strlen(haystack) || !strlen(separator)) ? NULL : haystack;
if (result != NULL)
{
result = strstr(haystack, separator);
if (result != NULL)
{
result = result + strlen(separator);
if(res == NULL) res = malloc(strlen(result) + 1);
if(res != NULL) strcpy(res, result);
result = res;
}
}
return result;
}
you can provide your own buffer to the function or if you pass NULL it will be allocated for you. But you need to remember to free it;

Splitting word by specific char work with string but don't work with argv[1]

I have an issue with my program.
My program split word using \t \n or space and put the word into a array of string.
when i call my function like this its works perfectly :
ft_print_words_tables(ft_split_whitespaces("Hello Everyone this is a test"));
but when i try to send the first command line param like this :
ft_print_words_tables(ft_split_whitespaces(argv[1]));
i'm getting the following error :
./a.out "test test tast"
a.out(97132,0x7fff706ff000) malloc: * error for object 0x7f9e09403228: incorrect checksum for freed object - object was probably modified after being freed.
* set a breakpoint in malloc_error_break to debug
[1] 97132 abort ./a.out "test test tast"
here is the code :
#include <stdlib.h>
// This func return the word nbr
int ft_compte_mot(char *str) {
int i = 0;
int j = 0;
while(str[i] == ' ' || str[i] == '\t' || str[i] == '\n') {
i++;
while (str[i] != '\0') {
if ((str[i] == ' ' || str[i] == '\n' || str[i] == '\t') &&
(str[i + 1] >= '!' && str[i + 1] <= 'z')) {
j++;
}
i++;
}
return (j + 1);
}
// this func count the word lenght and put them in an int array
int *ft_compte_taille_mot(int *taillemot, char *str) {
int i = 0;
int j = 0;
int k = 0;
while (str[i] != '\0') {
j = 0;
while ((str[i] == ' ' || str[i] == '\n' || str[i] == '\t')
&& str[i] != '\0')
i++;
while (str[i] != ' ' && str[i] != '\n' && str[i] != '\t'
&& str[i] != '\0') {
j++;
i++;
}
taillemot[k] = j;
i++;
k++;
}
return (taillemot);
}
void ft_copy_word(int *taillemot, int nbmot, char **tab, char *str) {
int i = 0;
int j = 0;
int k = 0;
while (str[i] != '\0' && k < nbmot) {
j = 0;
while ((str[i] == ' ' || str[i] == '\n' || str[i] == '\t')
&& str[i] != '\0')
i++;
while (j < taillemot[k]) {
tab[k][j] = str[i];
j++;
i++;
}
//tab[k][j] = '\0';
i++;
k++;
}
tab[nbmot] = 0;
}
char **ft_split_whitespaces(char *str) {
int nbmot = ft_compte_mot(str);
int *taillemot;
int i = 0;
char **string;
if ((taillemot = (int*)malloc(sizeof(int) * nbmot)) == NULL)
return (NULL);
ft_compte_taille_mot(taillemot, str);
if ((string = (char **)malloc(sizeof(char *) * (nbmot + 1))) == NULL)
return (NULL);
while (i < nbmot) {
if ((string[i] = (char *)malloc(sizeof(char) * taillemot[i] + 1))
== NULL)
return (NULL);
i++;
}
ft_copy_word(taillemot, nbmot, string, str);
return (string);
}
void ft_putchar(char c) {
write(1, &c, 1);
}
void ft_putstr(char *str) {
int i = 0;
while (str[i] != '\0') {
ft_putchar(str[i]);
i++;
}
}
void ft_print_words_tables(char **tab) {
int i;
i = 0;
while (tab[i] != 0) {
ft_putstr(tab[i]);
ft_putchar('\n');
i++;
}
ft_putchar('\n');
}
EDIT : Here is the main EDIT 2 : I also tested with argv[1]
char **ft_split_whitespaces(char *str);
void ft_print_words_tables(char **tab);
void ft_putchar(char c)
{
write(1, &c, 1);
}
int main(int argc, char **argv)
{
ft_print_words_tables(ft_split_whitespaces(argv[1]));
return (0);
}
FYI i'm in school and we have a particular norm, we can't use for loop or a bunch of libc function.
I'm really stuck here and i really don't understand why it's work with " " but not with **argv
thx by advance for your help
I found the solution :
char *str;
str = argv[1];
str[strlen(str) + 1] = '\0';
ft_print_words_tables(ft_split_whitespaces(str));
return (0);
thanks for the help

Resources