I have a javascript file, and I want to translate it in C, I did it but I have a big runtime error.
Everything work well until the end of the function when it return an int.
If you have some ideas where the bug is.
Thanks a lot.
#ifndef max
#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
#endif
char *substring(size_t start, size_t stop, const char *src, char *dst, size_t size)
{
int count = stop - start;
if ( count >= --size )
{
count = size;
}
sprintf(dst, "%.*s", count, src + start);
return dst;
}
int CrackLog(char log[], char pw[])
{
int tabc=3696619; //7
char tab[]=" azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789_$&##";
int i,checksum;
checksum=tabc;
int nblog=strlen(log);
int nbpass=6;//6
int sum=1;
int n = max(nblog,nbpass);
for (i=0;i<n;i++)
{
char *to;
to = substring(i, i+1, log, to, sizeof to);
int index1=strcspn(tab, to)+10;
to = substring(i, i+1, pw, to, sizeof to);
int index2=strcspn(tab, to)+10;
sum=sum+(index1*n*(i+1))*(index2*(i+1)*(i+1));
}
if (sum==checksum) {
return 1;
}else
return 0;
}
Forgive my english I am frensh.
Mac Fly
sprintf requires you allocate the memory yourself.
Try changing char *to;
to
char *to = (char*) malloc(sizeof(char)*(stop-start));
where start and stop are the first two arguments to substring
You might have to include stdlib.h if you haven't already
It looks like you are looping over the length of the two parameters log and pw. But since n appears as if it might be set to the maximum of those two lengths, then the substring call will be reading past the end of the shorter buffer at some point. In the given code, nbpass is hard coded to 6, so it is unclear exactly what the intent or result will be. Nonetheless, it seems that could be an issue (maybe you want a min result?).
As tzenes correctly points out, you need to make sure that the dst parameter of the substring call has a valid buffer to use. If you use malloc as he suggests, make sure you free it each time (if it is allocated each iteration).
However, the substring function is only extracting one character at a time. If that is the desired result, then the following might be more efficient:
char to[2];
to[1] = '\0'; // null terminate
for (i=0;i<n;i++)
{
to[0] = log[i];
int index1=strcspn(tab, to)+10;
to[0] = pw[i];
int index2=strcspn(tab, to)+10;
sum=sum+(index1*n*(i+1))*(index2*(i+1)*(i+1));
}
Related
I need to write c program to compare two strings without using strncpy() and then in another funtion check whether it works with using assert()
In my code by checking with pointers assert(*str2 == *"comp"); I only check the first letter and nothing else.So even there is another word starting with c, it will work.
char initialize_n(char str1[], char str2_n[], int n)
{
//initialize a string from the (at most) n first characters of another string
int i = 0;
for(i = 0; i < n; i++)
{
str2_n[i] = str1[i];
}
str2_n[i] = '\0';
}
void test_initialize_n(){
char str1[100] = "computer";
char str2[100];
initialize_n(str1, str2, 4);
assert(*str2 == *"comp");
}
How to correctly check it with assert?
So, without gcc extensions you can't put this into the assert body because the functions that would do so are forbidden to you.
What you need to do is write your own compare function and call it. Skeleton as follows:
int prefix_equals(const char *left, const char *right, int nleft, int nright)
{
if (nleft != nright) return 0;
/* Use the same for loop here you have in initialize_n */
if (left[i] != right[i]) return 0;
return 1; /* If you got all the way through they're equal */
}
assert(prefix_equals(str2, "comp", 4, 4));
In my experience the most useful form of this actually has two length arguments to save the caller from some ugliness in the call point. It seems wrong at assert level but it isn't wrong when you get to a few thousand lines.
I have been looking on internet for this and so far i just found a lot of questions for specific answer and not a general one.
i am kind of rusty on C. And i want to make a function that will return an array of char.
this is what i got and is not working. basically a way to convert a byte array to an array of chars to do atoi later..
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *get_char(int my_byte[], int packetsize)
{
char *array_char=(char *) malloc(sizeof(char)*10); //trying this but didnt work
// char array_char[10]; //i had it like this before(was told to do it)
for(int i=0;i<10;i++)
{
array_char[i]=my_byte[i]+0;
}
return array_char;
}
int main()
{
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp;
char data;
temp=get_char(byte_array,10);
data=*temp;
printf("String point %s ",data);
}
Two fixes:
As you want to convert to char, then
array_char[i]=my_byte[i]+0; should be array_char[i]=my_byte[i]+'0'; Note '0' is character (that will be converted to int) instead of numeric 0 (which doesn't do anything).
Also you must free temp pointer in main as that memory is dynamically allocated in get_char() function.
Edit: just notice another issue in your get_char()
char *array_char=(char *) malloc(sizeof(char)*10);
should be
char *array_char= malloc(sizeof(char)*(packetsize+1));
After the for loop, ensure the buffer is NUL-terminated:
array_char[packetsize] = '\0';
Notice that your packetsize is never used - you should get some compiler warning about it. It's bad to hard code 10 in your malloc - it's actually the whole idea of parsing the packetsize as a parameter - so use it properly.
You need to watch out for these things:
You need to add a null-terminating character at the end of *array_char, otherwise using this pointer allocated from the heap will cause undefined behaviour.
You can simply allocate *array_char like this:
char *array_char = malloc(packetsize+1);
As sizeof(char) is 1, and +1 for trailing nullbyte.
You also don't need to cast return of malloc().
Instead of passing 10 as packetsize to get_char(), you should pass this size as sizeof(arr) / sizeof(arr[0], which is the calculated size of the array. This can be a size_t variable declared somewhere or even a macro.
malloc() needs to be checked, as it can return NULL if unsuccessful.
You need to free() temp at some point in the program.
array_char[i]=my_byte[i]+0; needs to be array_char[i]=my_byte[i]+'0'; instead, as '0' is the ascii code for a zero character.
char data needs to be char *data, as temp is a pointer.
If you compile with -Wall -Wextra, you will see that this line:
data=*temp;
Is dangerous, and will trigger warnings of making pointers from integers without a cast. It will most likely lead to a segmentation fault. If temp and data are both pointers, then you can simply use:
data=temp;
Which sets data to the address of temp. Sometimes this is written as data = &(*temp);, but this is harder to read. Although their is no need for data, and using temp alone should be fine.
Your code can then look like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
char *get_char(int my_byte[], size_t packetsize) {
char *array_char = malloc(packetsize+1);
const char ascii = '0';
size_t i;
if (!array_char) {
printf("Cannot allocate %zu bytes\n", packetsize+1);
exit(EXIT_FAILURE);
}
for(i = 0; i < packetsize; i++) {
array_char[i] = my_byte[i] + ascii;
}
array_char[i] = '\0'; /* or array_char[packetsize] = '\0' */
return array_char;
}
int main(void) {
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp, *data;
temp = get_char(byte_array, ARRAYSIZE(byte_array));
data = temp;
printf("String point %s\n", data);
printf("String converted into number = %d\n", atoi(data));
free(temp);
temp = NULL;
return 0;
}
You can also look into strtol, which is better than using atoi() in terms of error checking.
It is Not Wise Idea to Return a Array From A Function. So how to return a string then? As most of libc functions use we can use some thing like that (i.e) passing a buffer along with our input and expect function to use output buffer to give us result.
Some issue to take care while coding
write your logic first.
try to use available functions from libc.
while dealing with byte data/binary data be take precaution of buffer overflow.
don't allocate in a function and de-allocate in another function.
Below is Example of your code with modification.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdint.h>
int get_char(uint8_t my_byte[], int packetsize, char *buffer, int max_buffer)
{
int byte_itr, buf_itr;
char temp_buf[16]={0x00};
for(byte_itr=0, buf_itr=0; byte_itr<packetsize && max_buffer > buf_itr; byte_itr++)
{
memset(temp_buf, 0x00, sizeof(temp_buf));
char temp_ch = my_byte[byte_itr];
snprintf(temp_buf, sizeof(temp_buf), "%d", temp_ch);
if( buf_itr+strlen(temp_buf) >=max_buffer){
break;
}else{
buf_itr += strlen(temp_buf);
strcat(buffer, temp_buf);
if(byte_itr+1 < packetsize){
strcat(buffer, ",");
buf_itr += 1;
}
}
}
return buf_itr;
}
int main()
{
uint8_t byte_array[]={1,2,3,4,5,6,7,8,9,0};
char char_array[32]={0x00};
int len = get_char(byte_array, 10, char_array, sizeof(char_array));
printf("String point %s : len %d\n", char_array, len);
}
NOTE:
when length return and size of output buffer same then buffer full condition happened.
The purpose of this function is to copy a string into a "buffer" - essentially another string. However, the problem seems overly complicated than what would be practical.
"Copies at most n-1 characters of string in into the buffer pointed to by
out. If n is reached, returns -2. Otherwise, returns -1 for malformed
input and 0 upon successful completion."
This is what I have:
#include <stdio.h>
#include <assert.h>
int copyStringN(register char *in, register char *out, register int n){
//Declarations
int i; //Dummy index
if(!in || !out) return -1;
for(i=0; i<n; i++){
*out++ = *in++;
}
*out = '\0';
return 0;
}
int main(void){
//Declarations
char in[] = "I'm not trying to inject malicious code...\\x29A.";
const int N = sizeof(in);
char out[N];
int err;
//Main execution
printf("\nThis function will copy at most n-1 characters of string into\nthe buffer pointed to by out.\n\n");
err = copyStringN(in, out, N);
assert(!err);
printf("%s\n", out);
printf("\nPlease press enter to exit...");
getchar();
return 0;
}
This general form was suggested, but it seems overly convoluted than what needs to be done. Why would n ever be reached? The execution should stop before n. Furthermore, wouldn't N = sizeof(in) match the length of the original string?
Personally, I would rather use a function closer to
int copyStringN(register char *in, register char *out)
{
if((!in || !out) && (sizeof(in)<=sizeof(out))) return -1;
else{
while(*t++ = *from++);
return 0;
}
}
int main(void){
//Declarations
char in[] = "I'm not trying to inject malicious code...\\x29A.";
const int N = sizeof(in);
char out[N];
int err;
.
.
.
I believe it would have the same effect with less statements. Let me make this more of a question, how could I write a function that copies a string into another array with the protection defined in the prompt? Also, are the two programs that I presented somehow vulnerable in a way I don't recognize?
Constructive input is appreciated.
This is a strange thing in C.
char mole[] = "mole" is not the same as char *mole = "mole"
I just tried:
char *a1 = "mole";
char a2[] = "mole";
printf ("s1: %i s2:%i\n", sizeof(a1), sizeof(a2) );
a1 is a pointer, so 4 or 8 depending on the architecture.
a2 is an array of size 5.
But you can convert a2 to a char* without warnings. But you loose the size.
Your suggested alternative will not work. (sizeof(in)<=sizeof(out) will always be TRUE, because you are comparing pointers (and not arrays), and they are the same size.
If you want to make safe string copy function, you must always pass output buffer length for size checking, and have means to inform user if input was too long for output.
Edit:
Since people have suggested to use strncpy, I will present safer alternative:
int len = snprintf(output, OUTPUT_SIZE, "%s", input);
if(len < 0 || len >= OUTPUT_SIZE) {
// Failed, handle error
}
Fewer statements in your source does not necessarily imply that it is simpler to grasp. The while row in your alternative solution may work, but is doing too many things at the same time for my taste. You are writing code first for other human beings to read, then for a compiler to read.
I like for example making the NULL and \0 checking explicit.
It is also unclear what you are trying to achieve with the sizeof comparison. Besides comparing size of pointers (instead of intended arrays?), I think you meant || instead of &&. If either pointer is NULL it is an error, whatever the size.
int copyStringN(char *in, char *out)
{
if((in == NULL) || (out == NULL)) {
return -1;
} else {
while(*in != '\0') {
*out++ = *in++;
}
*out = '\0';
return 0;
}
}
The compiled code is probably not going to be much different, only the source is more human readable in my opinion.
Then if there happens to be no '\0' in the in string you are going to have problems. I suppose this is the reason for having a length limit n.
while((*in != '\0') && (n-- > 0)) {
*out++ = *in++;
}
*out = '\0';
Note that you would still be in trouble if n is greater than the size of your arrays and you miss a '\0'.
A very similar interface is strncpy. Perhaps the error modes will make more sense after you read the man page.
It is always better to use strncpy to prevent buffer overflow. char * strncpy ( char * destination, const char * source, size_t num ); Also, better to use strlen rather than sizeof. So, Even if the source string is greater than the destination buffer. It will protect the destination buffer from buffer overflow. I would use n as the maximum size of the destination buffer. And In fact make n = strlen(dest_buffer) -1. To accommodate '\0'.
a basic strncpy would look like:
char *strncpy(char *d,const char *s,int n){int i=0;while(n--&&d[i++]=*s++);return d;}
but you could force a null byte at n-1
char *sstrncpy(char *d, const char *s, int n){
int i=0;
while(--n&&d[i++]=*s++);
if(!n)d[i]=0;
return d;
}
I am tring to create a sub-routine that inserts a string into another string. I want to check that the host string is going to have enough capacity to hold all the characters and if not return an error integer. This requires using something like sizeof but that can be called using a pointer. My code is below and I would be very gateful for any help.
#include<stdio.h>
#include<conio.h>
//#include "string.h"
int string_into_string(char* host_string, char* guest_string, int insertion_point);
int main(void) {
char string_one[21] = "Hello mother"; //12 characters
char string_two[21] = "dearest "; //8 characters
int c;
c = string_into_string(string_one, string_two, 6);
printf("Sub-routine string_into_string returned %d and creates the string: %s\n", c, string_one);
getch();
return 0;
}
int string_into_string(char* host_string, char* guest_string, int insertion_point) {
int i, starting_length_of_host_string;
//check host_string is long enough
if(strlen(host_string) + strlen(guest_string) >= sizeof(host_string) + 1) {
//host_string is too short
sprintf(host_string, "String too short(%d)!", sizeof(host_string));
return -1;
}
starting_length_of_host_string = strlen(host_string);
for(i = starting_length_of_host_string; i >= insertion_point; i--) { //make room
host_string[i + strlen(guest_string)] = host_string[i];
}
//i++;
//host_string[i] = '\0';
for(i = 1; i <= strlen(guest_string); i++) { //insert
host_string[i + insertion_point - 1] = guest_string[i - 1];
}
i = strlen(guest_string) + starting_length_of_host_string;
host_string[i] = '\0';
return strlen(host_string);
}
C does not allow you to pass arrays as function arguments, so all arrays of type T[N] decay to pointers of type T*. You must pass the size information manually. However, you can use sizeof at the call site to determine the size of an array:
int string_into_string(char * dst, size_t dstlen, char const * src, size_t srclen, size_t offset, size_t len);
char string_one[21] = "Hello mother";
char string_two[21] = "dearest ";
string_into_string(string_one, sizeof string_one, // gives 21
string_two, strlen(string_two), // gives 8
6, strlen(string_two));
If you are creating dynamic arrays with malloc, you have to store the size information somewhere separately anyway, so this idiom will still fit.
(Beware that sizeof(T[N]) == N * sizeof(T), and I've used the fact that sizeof(char) == 1 to simplify the code.)
This code needs a whole lot more error handling but should do what you need without needing any obscure loops. To speed it up, you could also pass the size of the source string as parameter, so the function does not need to calculate it in runtime.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
signed int string_into_string (char* dest_buf,
int dest_size,
const char* source_str,
int insert_index)
{
int source_str_size;
char* dest_buf_backup;
if (insert_index >= dest_size) // sanity check of parameters
{
return -1;
}
// save data from the original buffer into temporary backup buffer
dest_buf_backup = malloc (dest_size - insert_index);
memcpy (dest_buf_backup,
&dest_buf[insert_index],
dest_size - insert_index);
source_str_size = strlen(source_str);
// copy new data into the destination buffer
strncpy (&dest_buf[insert_index],
source_str,
source_str_size);
// restore old data at the end
strcpy(&dest_buf[insert_index + source_str_size],
dest_buf_backup);
// delete temporary buffer
free(dest_buf_backup);
}
int main()
{
char string_one[21] = "Hello mother"; //12 characters
char string_two[21] = "dearest "; //8 characters
(void) string_into_string (string_one,
sizeof(string_one),
string_two,
6);
puts(string_one);
return 0;
}
I tried using a macro and changing string_into_string to include the requirement for a size argument, but I still strike out when I call the function from within another function. I tried using the following Macro:
#define STRING_INTO_STRING( a, b, c) (string_into_string2(a, sizeof(a), b, c))
The other function which causes failure is below. This fails because string has already become the pointer and therefore has size 4:
int string_replace(char* string, char* string_remove, char* string_add) {
int start_point;
int c;
start_point = string_find_and_remove(string, string_remove);
if(start_point < 0) {
printf("string not found: %s\n ABORTING!\n", string_remove);
while(1);
}
c = STRING_INTO_STRING(string, string_add, start_point);
return c;
}
Looks like this function will have to proceed at risk. looking at strcat it also proceeds at risk, in that it doesn't check that the string you are appending to is large enough to hold its intended contents (perhaps for the very same reason).
Thanks for everyone's help.
Folks, here is an implementation of memset(), however I have been told that there is one logical mistake in the code. Could you help me find it.
I feel that a double pointer for the target string should be passed to this function, which will be like passing the address of the pointer variable and not the pointer itself.
I am getting an "access violation" when I execute the code in MS VC++ IDE.
The definition of the āCā Library function memset is
void *memset(char *s, char c, size_t n)
Copy c to the first n characters of s. Return s.
void *memset(char *s, char c, size_t n)
{
size_t i;
for (i = 0; i < n; i++, s++)
{
*s = c;
}
return s;
}
This has several problems.
void *memset(char *s, char c, size_t n)
{
size_t i;
for (i = 0; i < n; i++, s++) /* incrementing s means you cannot return */
{ /* the original value */
*s = c; /* consider using s[i] = c after not incr. s*/
}
return s; /* this should probably be a cast back to void */
}
You shouldn't be changing the pointer that is returned.
Check the return value of the function. What does it return? What is it documented to return?
I have a feeling that your size_t n may be off by one.
Also s points at the end of the string instead of the original s by the end of the function.
You modify the value of s and then return it. This means you will be returning a pointer to the end of the memset region, not the start (which is probably what you want)
You make the statement that you are getting a "access violation". That indicates that you are calling the function with a non-null value for 's', however, either 's' was not properly initialized
// bad - s will have some arbitrary value as allocated on the stack (all bets are off)
char *s;
memset(s,0,100);
// good
char s[100];
memset(s,0,100);
// bad - the memset will generate an access violation on byte 101
char s[100];
memset(s,0,101);
// good
char *s = malloc(100);
memset(s,0,100);
** one note not related to the access violation... returning 's' the way you do is not the same behavior as the traditional memset() in string.h. In that library, the return value is supposed to be the value of 's' as input. In your code you are returning a pointer to the byte after the last byte which would generate an access violation. for example:
// good
char *s = malloc(100);
char *d = memset(s,0,100);
printf("%s\n",d); // generates an access violation
in the memset() doc, d and s should have the same value. In your code, d = s[101];
Hum...
Try this:
void *memset (char* s, char c, size_t n){
char* begin = s;
char* end = begin + n;
whilw (begin != end) *begin++ = c;
return s;
}