Error that the stack was damaged while using strcat_s - c

I was studying strcat_s and I wrote the following code to practice it.
int main(void)
{
char szPath[128] = { "C:\\Program Files\\" };
strcat_s(szPath + strlen("C:\\Program Files\\"), sizeof(szPath), "CHS\\");
strcat_s(szPath + strlen("C:\\Program Files\\CHS\\"), sizeof(szPath), "C programming");
puts(szPath);
return 0;
}
The output worked properly like
C:\Program Files\CHS\C programming
but a debug error window popped up,
Stack around the variable 'szPath' was corrupted.
What is the cause?

If you send szPath + strlen("C:\\Program Files\\") as a parameter, then the size of the string is sizeof(szPath) - strlen("C:\\Program Files\\").
Same for the second line - size is sizeof(szPath) - strlen("C:\\Program Files\\CHS\\").
The string size is 128, but you send a pointer to the middle, where the number of available characters is smaller.

Looks like the debug version of strcat_s in visual studio deliberately overwrites the full length of the buffer:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strcat-s-wcscat-s-mbscat-s?view=vs-2019
The debug library versions of these functions first fill the buffer with 0xFE. To disable this behavior, use _CrtSetDebugFillThreshold.
This means that if you give a size value that is too large the debug runtime should detect this by corrupting the stack.
In your case you aren't passing a pointer to the beginning of the buffer so your size is strlen bytes more than the available space. The simplest solution to to just pass the pointer unmodified to strcat_s, it does the strlen internally to find the current end of the string:
int main(void)
{
char szPath[128] = { "C:\\Program Files\\" };
strcat_s(szPath, sizeof(szPath), "CHS\\");
strcat_s(szPath, sizeof(szPath), "C programming");
puts(szPath);
return 0;
}

Related

Freeing a buffer in C that was created in a function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 months ago.
Improve this question
I'm having some problems trying to free a buffer created in a function from outside that function in C. What I'm doing is to create bufA, do some stuff with it, then call a function which creates bufB, whose length is calculated inside that function. Bytes in bufA are then copied to bufB with some additional bytes added, then the function returns. Some further processing is done with bufB back in main(), then both bufA and bufB are freed. The program runs correctly, but throws an error when free(bufB) is called.
For very much simplified code, I have something like this:
typedef unsigned char BYTE;
// -----
int main(void) {
// -----
BYTE bufA = NULL;
// Specify lenBufA
bufA = calloc(lenBufA, 1);
// Populate bufA with some stuff.
BYTE bufB = NULL;
int lenBufB = myFunction(bufA, &bufB);
// Do something with bufB.
free(bufA);
free(bufB); // <=== Throws an error here.
return 0;
}
Then in myFunction() I may have something like this:
int myFunction(BYTE* inBuf, BYTE** outBuf) {
// Initialization.
// Calculate the length that outBuf will have and put it in outLen.
*outBuf = (BYTE*)calloc(outLen, 1);
// Do stuff with outBuf.
return outLen;
}
inBuf is not specified as constant as some bytes may be changed. calloc() rather than malloc() is used in main() and in the function because I want the bytes in both buffers to be initialized to zero, as a few bytes in both are not given values.
I'm using visual Studio 2022 with Windows 10. Somehow the error caused by free(bufB) must be related to the fact that memory is allocated in the function, not in main(). How is this fixed?
Your code is incomplete and does not compile. The main issue appears to be that the type of bufA and bufB is BYTE but should be a pointer BYTE *. Here is working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char BYTE;
int myFunction(const BYTE *inBuf, BYTE **outBuf) {
int outLen = strlen(inBuf);
*outBuf = calloc(outLen, 1);
if(!*outBuf) {
printf("calloc failed\n");
exit(1);
}
return outLen;
}
int main(void) {
BYTE *bufA = NULL;
int lenBufA = 42;
bufA = calloc(lenBufA, 1);
if(!bufA) {
printf("calloc failed\n");
exit(1);
}
memset(bufA, !'\0', lenBufA - 1); // heh
BYTE *bufB = NULL;
int lenBufB = myFunction(bufA, &bufB);
free(bufA);
free(bufB);
return 0;
}
It checks the return code of calloc, clarifies with const BYTE *inBuf that function doesn't change that argument.
On Googling ntdll.dll, it appears to be a Windows file of some type, and based on some blurb, it might be corrupted.
Accordingly, I copied the source files to another Windows 10 computer that also has Visual Studio 2022 installed, created a project, then compiled the source code. On executing I get the same message with different hex codes, However the hex code for sixbit-encoding6.exe is the same. Unfortunately the copy and paste feature of the mouse doesn't work for the message on that computer, but it thus looks as if the dll is probably not corrupted, and there is a problem with my application.

VS2010, scanf, strange behaviour

I'm converting some source from VC6 to VS2010. The code is written in C++/CLI and it is an MFC application. It includes a line:
BYTE mybyte;
sscanf(source, "%x", &mybyte);
Which is fine for VC6 (for more than 15 years) but causing problems in VS2010 so I created some test code.
void test_WORD_scanf()
{
char *source = "0xaa";
char *format = "%x";
int result = 0;
try
{
WORD pre = -1;
WORD target = -1;
WORD post = -1;
printf("Test (pre scan): stack: pre=%04x, target=%04x, post=%04x, sourse='%s', format='%s'\n", pre, target, post, source, format);
result = sscanf(source, format, &target);
printf("Test (post scan): stack: pre=%04x, target=%04x, post=%04x, sourse='%s', format='%s'\n", pre, target, post, source, format);
printf("result=%x", result);
// modification suggested by Werner Henze.
printf("&pre=%x sizeof(pre)=%x, &target=%x, sizeof(target)=%x, &post=%x, sizeof(post)=%d\n", &pre, sizeof(pre), &target, sizeof(target), &post, sizeof(post));
}
catch (...)
{
printf("Exception: Bad luck!\n");
}
}
Building this (in DEBUG mode) is no problem. Running it gives strange results that I cannot explain. First, I get the output from the two printf statemens as expected. Then a get a run time waring, which is the unexpected bit for me.
Test (pre scan): stack: pre=ffff, target=ffff, post=ffff, source='0xaa', format='%x'
Test (post scan): stack: pre=ffff, target=00aa, post=ffff, source='0xaa', format='%x'
result=1
Run-Time Check Failure #2 - Stack around the variable 'target' was corrupted.
Using the debugger I found out that the run time check failure is triggered on returning from the function. Does anybody know where the run time check failure comes from? I used Google but can't find any suggestion for this.
In the actual code it is not a WORD that is used in sscanf but a BYTE (and I have a BYTE version of the test function). This caused actual stack corruptions with the "%x" format (overwriting variable pre with 0) while using "%hx" (what I expect to be the correct format) is still causing some problems in overwriting the lower byte of variable prev.
Any suggestion is welcome.
Note: I edited the example code to include the return result from sscanf()
Kind regards,
Andre Steenveld.
sscanf with %x writes an int. If you provide the address of a BYTE or a WORD then you get a buffer overflow/stack overwrite. %hx will write a short int.
The solution is to have an int variable, let sscanf write to that and then set your WORD or BYTE variable to the read value.
int x;
sscanf("%x", "0xaa", x);
BYTE b = (BYTE)x;
BTW, for your test and the message
Run-Time Check Failure #2 - Stack around the variable 'target' was corrupted.
you should also print out the addresses of the variables and you'll probably see that the compiler added some padding/security check space between the variables pre/target/post.

Why's _itoa causing my program to crash?

The following code just keeps on crashing when it reaches the part with _itoa, I've tried to implement that function instead and then it got even weirder, it just kept on crashing when I ran it without the debugger but worked fine while working with the debugger.
# include "HNum.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# define START_value 30
typedef enum {
HNUM_OUT_OF_MEMORY = -1,
HNUM_SUCCESS = 0,
} HNumRetVal;
typedef struct _HNum{
size_t Size_Memory;
char* String;
}HNum;
HNum *HNum_alloc(){
HNum* first = (HNum*)malloc(sizeof(HNum));
if(first==NULL){
return NULL;
}
first->String =(char*)malloc(sizeof(START_value));
if(first->String==NULL){
return NULL;
}
first->Size_Memory = START_value; // slash zero && and starting from zero index;
return first;
}
HNumRetVal HNum_setFromInt(HNum *hnum, int nn){
itoa(nn,hnum->String,10);
}
void main(){
HNum * nadav ;
int h = 13428637;
nadav = HNum_alloc();
nadav->String="1237823423423434";
HNum_setFromInt(nadav,h);
printf("nadav string : %s \n ",nadav->String);
//printf("w string %s\n",w->String);
//printf("nadav string %s\n",nadav->String);
HNum_free(nadav);
}
I've been trying to figure this out for hours and couldn't come up with anything...
The IDE I'm using is Visual Studio 2012 express, the crash shows the following:
"PROJECT C.exe has stopped working
windows can check online for a solution to the program."
first->String =(char*)malloc(sizeof(START_value));
should be
first->String = malloc(START_value);
The current version allocates space for sizeof(int)-1 characters (-1 to leave space for the nul terminator). This is too small to hold your target value so _itoa writes beyond memory allocated for first->String. This results in undefined behaviour; it is quite possible for different runs to fail in different places or debug/release builds to behave differently.
You also need to remove the line
nadav->String="1237823423423434";
which leaks the memory allocated for String in HNum_alloc, replacing it with a pointer to a string literal. This new pointer should be considered to be read-only; you cannot write it it inside _itoa
Since I'm not allowed to comment:
simonc's answer is correct. If you find the following answer useful, you should mark his answer as the right one:P
I tried that code myself and the only thing missing is lets say:
strcpy(nadav->String, "1237823423423434"); INSTEAD OF nadav->String="1237823423423434";
and
first->String = malloc(START_value); INSTEAD OF first->String =(char*)malloc(sizeof(START_value));
Also, maybe you'd have to use _itoa instead of itoa, that's one of the things I had to change in my case anyhow.
If that doesn't work, you should probably consider using a different version of VS.

Linux kernel: why does this call to kstrtol crash?

I am learning kernel programming and have a simple call to kstrtol I am using to convert a string to a number. However, everytime I compile this module and use insmod to place it in the kernel, I get "BUG: unable to handle kernel paging request at f862b026" and then a register and stack dump.
I'm following the definition from here: https://www.kernel.org/doc/htmldocs/kernel-api/API-kstrtol.html. It seems like a really simple call. What am I doing wrong here?
#include <linux/kernel.h>
static int __init convert(void)
{
long myLong;
char *myNumber = "342";
myNumber[2] = '\0'; //Overwriting the '2', just so I know for sure I have a terminating '\0'
if (kstrtol(myNumber, 10, &myLong) == 0)
{
printk("We have a number!\n");
}
return 0;
}
static void __exit convert_exit(void)
{
printk("Module unloaded\n");
}
module_init(convert);
module_exit(convert_exit);
You cannot modify string literals. Copy it into an array firstly.
edit: use this instead
char mystr[] = "abdc";
edit2:
the underlying reason for this is, that a char pointer to a string literal points to a data segment, usually readonly. If you alter this memory you might get a crash.
When you create an array of chars instead, the string literal gets copied into the array on the stack, where you safely can modify it.

Redis: SET command when data starts with a newline character

I'm using Redis in a C program I'm writing (with hiredis C binding).
Here is my code:
void insert(redisContext* c,char* buf){
static redisReply *reply;
const char* hash="asdf";
char* cmd=(char*)malloc((strlen("SET ")+strlen(hash)+strlen(" ")+CHUNKSIZE)*sizeof(char));
//hash=getHash(buf);
memcpy(cmd,"SET ",(size_t)strlen("SET "));
memcpy(cmd+strlen("SET "),hash,(size_t)strlen(hash));
memcpy(cmd+strlen("SET ")+strlen(hash)," ",(size_t)strlen(" "));
memcpy(cmd+strlen("SET ")+strlen(hash)+strlen(" "),buf,(size_t)CHUNKSIZE);
fwrite(cmd,strlen("SET ")+strlen(hash)+strlen(" ")+CHUNKSIZE,sizeof(char),stdout);
printf("\n\n\n\n\n\n");
reply=(redisReply*)redisCommand(c,cmd);
freeReplyObject(reply);
free(cmd);
}
As you can see, the cmd looks like: SET asdf xxx, where xxx is 512 bytes long (binary data).
The problem arises when the binary data string begins with '\n'. I keep getting an error (segmentation fault).
Anyone have any ideas?
Many thanks in advance,
I'm using the code you posted and didn't get any crash.
My code is:
#define CHUNKSIZE 512
char asd[CHUNKSIZE];
memset(asd, 0, 512);
asd[0] = '\n';
insert(c, asd);
Try running your app with valgrind that will probably give you a better idea of what's wrong before it crashes.
hiredis docs:
When you need to pass binary safe strings in a command, the %b specifier can be used. Together with a pointer to the string, it requires a size_t length argument of the string:
reply = redisCommand(context, "SET foo %b", value, valuelen);

Resources