I am new to C programming and I am getting confused with the pointer math. I have an array of characters of size 32. It is my understanding that this means that the array is also 32 bytes since a character variable is 1 byte big therefore 32 characters * 1 byte = 32 bytes. The problem is when having a function that has a void pointer that is pointing to an array of characters as described before. I believe that the code segment
for (count = 0; count < size; count++)
*((int*) raw_sk + count) = 0
should set all of the slots in the raw_sk buffer should be set to 0. However, when I run the program, I get a segmentation fault. I thought that it could be possibly be the fact that I am adding count to the address. I thought that if I were to add one to an address I would be moving to the next slot in the array. Can someone please point out where I am going wrong? The function I am using is below.
Thanks!
void
write_skfile (const char *skfname, void *raw_sk, size_t raw_sklen)
{
int fdsk = 0;
char *s = NULL;
int status = 0;
int count = 0;
int size = (raw_sklen);
/* armor the raw symmetric key in raw_sk using armor64 */
s = armor64(raw_sk, raw_sklen);
/* now let's write the armored symmetric key to skfname */
if ((fdsk = open (skfname, O_WRONLY|O_TRUNC|O_CREAT, 0600)) == -1) {
perror (getprogname ());
/*scrubs the armored buffer*/
for(count = 0; count < armor64len(s); count++)
s[count] = '0';
free (s);
/* scrub the buffer that's holding the key before exiting */
for (count = 0; count < size; count++)
*((int*)raw_sk + count) = 0;
exit (-1);
}
else {
status = write (fdsk, s, strlen (s));
if (status != -1) {
status = write (fdsk, "\n", 1);
}
for (count = 0; (size_t)count < 22; count++)
*((int*)raw_sk + count) = 0;
free (s);
close (fdsk);
/* do not scrub the key buffer under normal circumstances
(it's up to the caller) */
if (status == -1) {
printf ("%s: trouble writing symmetric key to file %s\n",
getprogname (), skfname);
perror (getprogname ());
/* scrub the buffer that's holding the key before exiting */
/* scrub the buffer that's holding the key before exiting MY CODE
for (count = 0; count < size; count++)
*((int*)raw_sk + count) = 0;*/
exit (-1);
}
}
}
You are incrementing the pointer by the size of an int. That is wrong. If you want to zero out the array you increment by the size of a char. Better yet, just use memset.
Your loop iterates over size*sizeof(int) bytes in total (where most probably sizeof(int)==4), but the array is only size bytes large. Hence, segmentation fault.
I think you meant to do
*((char*) raw_sk + count) = 0
since I assume raw_sk is pointing to char array
pointer arithmatic works by moving the memory address by size of type so in this case you want char
Related
I am trying to solve a "suppose to be" a simple C question.
Q: Receive "infinite" input by user using int pointer until EOF received using malloc and realloc.
I defined a int pointer like this:
int *inputBuffer = NULL;
and initialized it using this method:
/* #define BUFFER_SIZE 8 - already defined at top of code, posted here for more info */
/* Creates buffer by using malloc -
if succeded returns true, otherwise false */
int createBuffer(int **inputBuffer)
{
*inputBuffer = (int*) calloc(BUFFER_SIZE, sizeof(char)); /* Allocate memory to get input from user */
if(*inputBuffer == NULL)
return FALSE;
return TRUE;
}
by calling createBuffer(&inputBuffer)
so far so good, memory is allocated successfully.
before starting to receive characters from user I defined the following properties:
int totalCharacters = 0;
int bufferExtendsCounter = 1;
int character;
Next step is to receive characters inputs from user like this:
/* #define MEMORY_SAFE_GAP 4 - already defined at top of code, posted here for more info */
while((character = getchar()) != EOF && inputBuffer != NULL)
{
/* Check if reallocate needs to be called since almost maxed out buffer */
if(totalCharacters - MEMORY_SAFE_GAP > (BUFFER_SIZE * bufferExtendsCounter))
{
/* Add 1 to extends buffer times */
bufferExtendsCounter+=1;
if(!extendBuffer(&inputBuffer, totalCharacters))
printf("\nFailed to allocate more memory.");
}
/* Initialize buffer with character, this is safe since there is a memory safe gap */
inputBuffer[totalCharacters] = character;
totalCharacters++;
}
extend buffer looks like this:
/* Extends buffer size by using realloc
if succeded returns true, otherwise false */
int extendBuffer(int **inputBuffer, int minimumBufferSize)
{
/* Check how many times buffer needs to be multiple (at least) */
int multipleBufferNumber = (minimumBufferSize / BUFFER_SIZE) + 1;
int newBufferSize = BUFFER_SIZE * multipleBufferNumber * sizeof(char);
while(newBufferSize < minimumBufferSize)
{
multipleBufferNumber+=1;
newBufferSize = BUFFER_SIZE * multipleBufferNumber * sizeof(char);
}
/* Reallocate memory for next chunck of data */
*inputBuffer = realloc(*inputBuffer, newBufferSize);
/* Check if memory successfully allocated */
if(*inputBuffer == NULL)
return FALSE;
return TRUE;
}
It looks like I extend the buffer size enough for more input by user, but still gets error:
corrupted size vs. prev_size: 0x08f86010 ***
Example input:
TestProgramTest (Pressed Enter after last 't')
(DebugPrint: Received 13 characters)
(DebugPrint: Reallocating to size 16)
*** Error in `./test': corrupted size vs. prev_size: 0x08f86010 ***
EDIT (Due to lack of code parts):
The following part is right after while loop:
inputBuffer[totalCharacters] = '\0';
printf("\nInput by user:\n");
/* #define LINE_LENGTH 5 - already defined at top of code, posted here for more info */
printBuffer(inputBuffer, LINE_LENGTH, totalCharacters);
/* free memory */
free(inputBuffer);
and printBuffer looks like:
/* Prints the buffer data to pretty output */
void printBuffer(int *inputBuffer, int lineLength, int totalCharacters)
{
int i;
for(i = 0; i < totalCharacters; i++)
{
/* Print each char value */
printf("%c", inputBuffer[i]);
/* Check if got to line limit, if so enter new line */
if((i+1) % lineLength == 0)
printf("\n");
}
}
Second edit:
Changed all int pointer parts to char pointer.
Full code looks like:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define LINE_LENGTH 5
#define BUFFER_SIZE 8
#define TRUE 1
#define FALSE 0
#define MEMORY_SAFE_GAP 4
int createBuffer(char **inputBuffer);
int extendBuffer(char **inputBuffer, int minimumBufferSize);
void printBuffer(char *inputBuffer, int lineLength, int totalCharacters);
int main(void)
{
char *inputBuffer = NULL;
if(!createBuffer(&inputBuffer))
{
printf("Memory cannot be allocated, program will exit now.");
exit(-1);
}
int totalCharacters = 0;
int bufferExtendsCounter = 1;
char character;
printf("Please enter a string:\n");
/* Loop till EOF received */
while((character = getchar()) != EOF && inputBuffer != NULL)
{
/* Check if reallocate needs to be called since almost maxed out buffer */
if(totalCharacters - MEMORY_SAFE_GAP > (BUFFER_SIZE * bufferExtendsCounter))
{
/* Add 1 to extends buffer times */
bufferExtendsCounter+=1;
if(!extendBuffer(&inputBuffer, totalCharacters))
printf("\nFailed to allocate more memory.");
}
/* Initialize buffer with character, this is safe since there is a memory safe gap */
inputBuffer[totalCharacters] = character;
totalCharacters++;
}
inputBuffer[totalCharacters] = '\0';
printBuffer(inputBuffer, LINE_LENGTH, totalCharacters);
/* free memory */
free(inputBuffer);
return 0;
}
/* Creates buffer by using malloc
if succeded returns true, otherwise false */
int createBuffer(char **inputBuffer)
{
/* Allocate memory to get input from user */
*inputBuffer = (char*) calloc(BUFFER_SIZE, sizeof(char));
if(*inputBuffer == NULL)
return FALSE;
return TRUE;
}
/* Extends buffer size by using realloc
if succeded returns true, otherwise false */
int extendBuffer(char **inputBuffer, int minimumBufferSize)
{
/* Check how many times buffer needs to be multiple (at least) */
int multipleBufferNumber = (minimumBufferSize / BUFFER_SIZE) + 1;
int newBufferSize = BUFFER_SIZE * multipleBufferNumber * sizeof(char);
while(newBufferSize < minimumBufferSize)
{
multipleBufferNumber+=1;
newBufferSize = BUFFER_SIZE * multipleBufferNumber * sizeof(char);
}
/* Reallocate memory for next chunck of data */
*inputBuffer = realloc(*inputBuffer, newBufferSize);
/* Check if memory successfully allocated */
if(*inputBuffer == NULL)
return FALSE;
return TRUE;
}
/* Prints the buffer data to pretty output */
void printBuffer(char *inputBuffer, int lineLength, int totalCharacters)
{
printf("Printing buffer\n");
int i;
for(i = 0; i < totalCharacters; i++)
{
/* Print each char value */
printf("%c", inputBuffer[i]);
/* Check if got to line limit, if so enter new line */
if((i+1) % lineLength == 0)
printf("\n");
}
}
Any help would be great!
Thanks in advance.
Right here
*inputBuffer = (int*) calloc(BUFFER_SIZE, sizeof(char));
You reserve space for 8 chars but try to store 8 ints in it
Why isnt inputBuffer just a char*? since thats what you are storing
Now you have fixed that - look at this
if (totalCharacters - MEMORY_SAFE_GAP > (BUFFER_SIZE * bufferExtendsCounter))
I do not know what the intention of the 'MEMORY_SAFE_GAP' is but its wrong
Look at what happens when I input character number 8
if(8 - 4 > 8 * 1)
is false, so you do not extend the buffer.
This 'SAFE-GAP ensure that you always run off the end, your code no longer crashes if you just have
if (totalCharacters >= (BUFFER_SIZE * bufferExtendsCounter))
output is still a little garbled but you can probably fix that. I input 1234567890 and got
Please enter a string:
1234567890
^Z
Printing buffer
12345
678═0
For this code below that I was writing. I was wondering, if I want to split the string but still retain the original string is this the best method?
Should the caller provided the ** char or should the function "split" make an additional malloc call and memory manage the ** char?
Also, I was wondering if this is the most optimizing method, or could I optimize the code better than this?
I still have not debug the code yet, I am a bit undecided whether if the caller manage the ** char or the function manage the pointer ** char.
#include <stdio.h>
#include <stdlib.h>
size_t split(const char * restrict string, const char splitChar, char ** restrict parts, const size_t maxParts){
size_t size = 100;
size_t partSize = 0;
size_t len = 0;
size_t newPart = 1;
char * tempMem;
/*
* We just reverse a long page of memory
* At reaching the space character that is the boundary of the new
*/
char * mem = (char*) malloc( sizeof(char) * size );
if ( mem == NULL ) return 0;
for ( size_t i = 0; string[i] != 0; i++ ) {
// If it is a split char we at a new part
if ( string[i] == splitChar) {
// If the last character was not the split character
// Then mem[len] = 0 and increase the len by 1.
if (newPart == 0) mem[len++] = 0;
newPart = 1;
continue;
} else {
// If this is a new part
// and not a split character
// we make a new pointer
if ( newPart == 1 ){
// if reach maxpart we break.
// It is okay here, to not worry about memory
if ( partSize == maxParts ) break;
parts[partSize++] = &mem[len];
newPart = 0;
}
mem[len++] = string[i];
if ( len == size ){
// if ran out of memory realloc.
tempMem = (char*)realloc(mem, sizeof(char) * (size << 1) );
// if fail quit loop
if ( tempMem == NULL ) {
// If we can't get more memory the last part could be corrupted
// We have to return.
// Otherwise the code below can seg.
// There maybe a better way than this.
return partSize--;
}
size = size << 1;
mem = tempMem;
}
}
}
// If we got here and still in a newPart that is fine no need
// an additional character.
if ( newPart != 1 ) mem[len++] = 0;
// realloc to give back the unneed memory
if ( len < size ) {
tempMem = (char*) realloc(mem, sizeof(char) * len );
// If the resizing did not fail but yielded a different
// memory block;
if ( tempMem != NULL && tempMem != mem ){
for ( size_t i = 0; i < partSize; i++ ){
parts[i] = tempMem + (parts[i] - mem);
}
}
}
return partSize;
}
int main(){
char * tStr = "This is a super long string just to test the str str adfasfas something split";
char * parts[10];
size_t len = split(tStr, ' ', parts, 10);
for (size_t i = 0; i < len; i++ ){
printf("%zu: %s\n", i, parts[i]);
}
}
What is "best" is very subjective, as well as use case dependent.
I personally would keep the parameters as input only, define a struct to contain the split result, and probably return such by value. The struct would probably contain pointers to memory allocation, so would also create a helper function free that memory. The parts might be stored as list of strings (copy string data) or index&len pairs for the original string (no string copies needed, but original string needs to remain valid).
But there are dozens of very different ways to do this in C, and all a bit klunky. You need to choose your flavor of klunkiness based on your use case.
About being "more optimized": unless you are coding for a very small embedded device or something, always choose a more robust, clear, easier to use, harder to use wrong over more micro-optimized. The useful kind of optimization turns, for example, O(n^2) to O(n log n). Turning O(3n) to O(2n) of a single function is almost always completely irrelevant (you are not going to do string splitting in a game engine inner rendering loop...).
I'm currently writing a method that reads from an allocated block of memory and prints out its contents from a certain offset and up to a specified size, both of which are passed as parameters. I'm using char pointers to accomplish this, but keep getting a malloc error around line
char *content = (char *)malloc(size+1);
Code for the method:
int file_read(char *name, int offset, int size)
{
//First find file and its inode, if existing
int nodeNum = search_cur_dir(name);
if(nodeNum < 0) {
printf("File read error: file does not exist\n");
return -1;
}
//Size check, to avoid overflows/overreads
if(offset > inode[nodeNum].size || size > inode[nodeNum].size || (offset+size) > inode[nodeNum].size) {
printf("File read error: offset and/or size is too large\n");
return -1;
}
int i, read_size, track_size = size, content_offset = 0;
int target_block = offset / BLOCK_SIZE; //Defined as constant 512
int target_index = offset % BLOCK_SIZE;
char *raw_content = (char *)malloc(inode[nodeNum].size+1);
printf("check1\n"); //Debug statment
for(i = target_block; i < (inode[nodeNum].blockCount-(size/BLOCK_SIZE)); i++) {
disk_read(inode[nodeNum].directBlock[i], raw_content+content_offset);
content_offset += BLOCK_SIZE;
}
printf("check2\n"); //Debug statment
char *content = (char *)malloc(size+1);
memcpy(content, raw_content+target_index, size);
printf("%s\n", content);
free(raw_content);
free(content);
return 0;
}
and code for disk_read:
char disk[MAX_BLOCK][BLOCK_SIZE]; //Defined as 4096 and 512, respectively
int disk_read(int block, char *buf)
{
if(block < 0 || block >= MAX_BLOCK) {
printf("disk_read error\n");
return -1;
}
memcpy(buf, disk[block], BLOCK_SIZE);
return 0;
}
structure for node
typedef struct {
TYPE type;
int owner;
int group;
struct timeval lastAccess;
struct timeval created;
int size;
int blockCount;
int directBlock[10];
int indirectBlock;
char padding[24];
} Inode; // 128 byte
The error I get when using this method is one of memory corruption
*** glibc detected *** ./fs_sim: malloc(): memory corruption (fast): 0x00000000009f1030 ***
Now the strange part is, firstly this only occurs after I have used the method a few times - for the first two or three attempts it will work and then the error occurs. For instance, here is an example test run:
% read new 0 5
z12qY
% read new 0 4
z12q
% read new 0 3
*** glibc detected *** ./fs_sim: malloc(): memory corruption (fast): 0x00000000009f1030 ***
Even stranger still, this error disappears completely when I comment out
free(raw_content);
free(content);
Even through this would tie up the memory. I've read through previous posts regarding malloc memory corruption and understand this usually results from overwriting memory bounds or under allocating space, but I can't see where I could be doing this. I've attempted other sizes for malloc as well and these produced the best results when I commented out the lines freeing both pointers. Does anyone see what I could be missing? And why does this occur so inconsistently?
Code allocates space for characters and a null character, but does not insure the array is terminated with a null character before printing as a string.
char *content = (char *)malloc(size+1);
memcpy(content, raw_content+target_index, size);
// add
content[size] = '\0';
printf("%s\n", content);
Likely other issues too.
[Edit]
OP code is prone to mis-coding and dependent on inode[] to have coherent values (.blockCount . size). Clarify and simplify by determining the loop count and allocating per that count.
int loop_count = (inode[nodeNum].blockCount-(size/BLOCK_SIZE)) - target_block;
char *raw_content = malloc(sizeof *raw_content * loop_count * BLOCK_SIZE);
assert(raw_count);
for (loop = 0; loop < loop_count; loop++) {
i = target_block + loop;
disk_read(inode[nodeNum].directBlock[i], raw_content + content_offset);
content_offset += BLOCK_SIZE;
}
Also recommend checking the success of disk_read()
gcc (GCC) 4.7.2
valgrind-3.8.1
c89
Hello,
==1160== Invalid read of size 1
==1160== at 0x8048C94: get_input_values (parse_cmd_input.c:278)
==1160== by 0x8048BA0: parse_input (parse_cmd_input.c:245)
==1160== by 0x80489A1: main (parse_cmd_input.c:50)
==1160== Address 0x40ef02c is 0 bytes after a block of size 4 alloc'd
==1160== at 0x40072C5: calloc (vg_replace_malloc.c:593)
==1160== by 0x8048B28: parse_input (parse_cmd_input.c:239)
==1160== by 0x80489A1: main (parse_cmd_input.c:50)
So its saying the address is reading a zero bytes of a allocated size of 4, and is trying to read 1 byte from it. However, I haven't over stepped the bounds of the array and I am accessing element 0.
I have checked with gdb, and element zero contains a character.
My program doesn't crash, and seems to work fine. But it might cause a problem on a production server.
I am not sure if I am correct here:
Should this be:
cpy_input = calloc(strlen(input) + 1, sizeof(char*));
or:
cpy_input = calloc(strlen(input) + 1, sizeof(char));
A char is 1 byte, and a pointer to a char is 4 bytes on my system.
The string passed in would be something like this "25 b"
int parse_input(const char *input)
{
char *cpy_input = NULL;
int has_error = -1;
if(strlen(input) == 0) {
LOG_ERR("FAILED: Empty string");
return -1;
}
cpy_input = calloc(strlen(input) + 1, sizeof(char));
apr_cpystrn(cpy_input, input, sizeof(cpy_input));
LOG_INFO("[ %s ]", cpy_input);
memset(&channel, 0, sizeof channel);
has_error = get_input_values(cpy_input, &channel);
free(cpy_input);
return has_error;
}
int get_input_values(const char *str, channel_t *channel)
{
size_t i = 0;
size_t k = 0;
int upper_flag = 0;
/* Indicates no digits or command found*/
channel->lower = -1;
channel->upper = -1;
channel->cmd = -1;
#define DIG_BUFFER_SIZE 32
char dig_buffer_lower[DIG_BUFFER_SIZE];
char dig_buffer_upper[DIG_BUFFER_SIZE];
if(strlen(str) == 0) {
LOG_ERR("FAILED: Empty string");
return -1;
}
memset(dig_buffer_lower, 0, DIG_BUFFER_SIZE);
memset(dig_buffer_upper, 0, DIG_BUFFER_SIZE);
LOG_INFO("SIZE %d %d", sizeof(char), sizeof(char*));
/* Increament and check for digits */
for(i = 0; i < DIG_BUFFER_SIZE; i++) {
switch(str[i]) {
case 32: /* ignore space */
continue;
case 45: /* '-' Start upper bounds */
LOG_DEBUG("Found a '-' check upper value");
/* Having a second '-' means the string is invalid */
if(!upper_flag) {
upper_flag = 1;
k = 0;
}
break;
} /* switch */
/* Insert on digits into the lower and upper values */
if(isdigit(str[i])) {
if(upper_flag) {
dig_buffer_upper[k++] = str[i];
LOG_DEBUG("dig_buffer_upper[%d] %s", i, dig_buffer_upper);
}
else {
/* Add to digit buffer */
dig_buffer_lower[k++] = str[i];
LOG_DEBUG("dig_buffer_lower[%d] %s", i, dig_buffer_lower);
}
}
} /* for loop */
Many thanks for any suggestions,
sizeof(cpy_input) is just sizeof(char *), and not the string length. Instead, say:
apr_cpystrn(cpy_input, input, strlen(input) + 1);
Or better, use a naked strcpy or equivalent. Also there's no need to zero out the array with calloc, since you're just about to overwrite it anyway. And since sizeof(char) is 1 by definition, you can allocate the array with:
cpy_input = malloc(strlen(input) + 1);
(Think about strings for a minute: You're already at the mercy of having a null terminator at a sensible place, or strlen will either crash or return a huge value. Once you trust the result of strlen, you are guaranteed to allocate enough memory to strcpy the string and the null terminator. Alternatively, you can use memcpy for a possibly even more efficient copy, since you know the size.)
Ok, maybe I'm missing something, but your for loop will iterate over 0 .. DIG_BUFFER_SIZE-1, reading from str[i]. I don't see what would cause that loop to break out early, especially since it seems to immediately wrap a switch, and so any break inside the switch would exit the switch, but not the for.
Your calloc(strlen(input) + 1, sizeof(char)); correctly allocates storage for the exact length of input. The code downstream in get_input_values doesn't seem to stop if the string is shorter than DIG_BUFFER_SIZE.
(I'd love to be proven wrong, but to know, we need to see more code.)
I am having an issue with recv. I wrote a function that fills a structure with data, and the length (in bytes) of that data which is read from a socket.
For testing I am just printing the data to stdout byte by byte based on the total amount of bytes read by recv. For some reason the number of bytes being read seems to be correct sometimes and incorrect other times depending on what site I am querying. For example the following code works as intended on some sites:
data->data_sz = 0;
while((i = recv(sock, data->data + data->data_sz, CHUNKSIZE, 0)) > 0)
{
data->data_sz += i;
if(databff - data->data_sz < CHUNKSIZE)
{
databff *= 2;
if(!(tmp = realloc(data->data, databff)))
{
free(data->data);
(void) WSACleanup();
return 0;
}
data->data = tmp;
}
}
i = strsbstr(data->data, "\r\n\r\n") + 4; //i = the position of the first char after header info
if(i >= 0)
{
data->data_sz = data->data_sz - i; //data->data_sz = number of bytes without header info
memmove(data->data, data->data + i, data->data_sz);
if(!(tmp = realloc(data->data, data->data_sz)))
{
free(data->data);
(void)WSACleanup();
return 0;
}
data->data = tmp;
}
else
{
free(data->data);
(void) WSACleanup();
return 0;
}
return 1;
}
To print the data to stdout I just use a for loop:
//t_html->data_sz points to my data->data_sz structure
//t_html->data points to my data->data structure
for(i = 0; i <= t_html->data_sz; i++) (void)fputc((int)t_html->data[i], stdout);
The above code works for some sites but fails on others (for example when querying http://www.google.com I expect the final characters to be </html> but I get </html>l).
Basically my problem is that data->data_sz (the amount of bytes received) is not being calculated correctly, which makes it impossible to correctly use gathered data. I am really at a loss of what to do right now.
EDIT:
here is the strsbstr function which is called in the above code:
int strsbstr(const char *str, const char *sbstr)
{
char *sbstrlc;
if(!(strcmp(str, sbstr))) return 0;
if(!(sbstrlc = strstr(str, sbstr))) return -1;
return (int) (sbstrlc - str);
}
recv(sock, data->data + data->data_sz, CHUNKSIZE, 0) is potentially a problem. Why? Because you may not have CHUNKSIZE room left in your buffer. You have databff - data->data_sz left, actually (assuming data is allocated to a size of databff). It all depends on the initial values of databff and CHUNKSIZE, which I can't see and figure I'd point this out just in case.
Data is not guaranteed to be NULL-character terminated. Your printing loop says i <= t_html->data_sz; which is wrong. It should be i < t_html->data_sz;. If you use <=, you're accessing one past your buffer, which is likely why you get a weird character sometimes, and sometimes not.