Expression: (L "String is not null terminated" & & 0) - c

I am fiddling around with mailslots and now I've run into a problem.
Whenever I try to run, I get the error message in the title, but I don't know how I should go about fixing it.
What I am trying to do is "fixing" the full path of the mailslot, but it seems to not like the strcat_s-part.
HANDLE mailslotCreate (char *name) {
char fullName[50] = "\\\\.\\mailslot\\";
strcat_s(fullName, strlen(fullName), name);
return CreateMailslot(fullName, 0, TIME_OUT, NULL);
}
Imgur link to error
EDIT: Changing the strlen to sizeof merely changed the error to "Buffer size too small" instead.

See documentation on strcat_s. It says that second parameter should be the size of destination buffer. As you pass strlen(fullName), there is no room for terminating \0.
Change it to be sizeof(fullName) and your error should disappear.

Related

Opening registry key in c

I have create a key using regedit, now I want to get its value. It doesn't give any error but it isn't showing anything.
Code :
int main() {
HKEY hKey;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Ehsan Akbari", 0, KEY_ALL_ACCESS, &hKey);
TCHAR sz[50];
DWORD size = 50,type;
RegEnumValue(hKey, 0, L"test", &size, NULL, &type, (LPBYTE)sz, &size);
RegCloseKey(hKey);
getch();
return 0;
}
An image of regedit :picture
What am I doing wrong?
Edit
When I debugged I saw that hKey is NULL, but GetLastError doesn't report anything.
Here are the immediate problems that I can see:
You detect no errors because you don't check for errors. Read the documentation for each function. The error code is returned in the return value.
You ask for KEY_ALL_ACCESS which won't be granted under HKLM. You need to request just read access KEY_READ.
Your screenshot shows the key has been created under HKCU, and you're trying to open it under HKLM.
RegEnumValue expects the size of the data buffer in bytes. You pass the length, the number of characters.
You are mixing Unicode literals and TCHAR. This is pointless. Your code won't compile targeting MBCS and in any case you don't care about Win98 any more. Stop using TCHAR and use wchar_t instead.
The lpValueName parameter must be a modifiable buffer. You pass a literal. Remember that this function enumerates values. It does not read specific named values as perhaps you expect.
The lpcchValueName parameter contains the size of the buffer you passed to lpcchValue in characters. You pass the length of the data buffer.
The data returned may not be null terminated. You must protect against this as described in the documentation.
For a C program which ignores its arguments, the correct main is int main(void).
I expect there are more errors but I stopped looking at this point. I recommend you spend some quality time with the documentation.
To open the path "Ehsan Akbari" in HKEY_CURRENT_USER you could try this:
HKEY hKey;
long result = RegOpenKeyEx(HKEY_CURRENT_USER , TEXT("\\Ehsan Akbari"), 0, KEY_ALL_ACCESS, &hKey);
if ( result == ERROR_SUCCESS )
{
cout << "OK" << endl;
}
else
{
cout << "Error " << result << endl;
}

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.

Tainted string in C

I'm running Coverity tool in my file operation function and getting the following error.
As you can see below, I'm using an snprintf() before passing this variable in question to the line number shown in the error message. I guess that some sanitization of the string has to be done as a part of that snprintf(). But still the warning is shown.
Error:TAINTED_STRING (TAINTED string "fn" was passed to a tainted string sink content.) [coverity]
char fn[100]; int id = 0;
char* id_str = getenv("ID");
if (id_str) {
id = atoi(id_str);
}
memset(fn, '\0', sizeof(fn));
snprintf(fn, 100, LOG_FILE, id);
if(fn[100-1] != '\0') {
fn[100-1] = '\0';
}
log_fp = fopen (fn, "a");
Any help would be highly appreciated.
Try the following:
char* id_str = getenv("ID");
if (id_str) {
id_str = strdup(id_str);
id = atoi(id_str);
free( id_str );
}
The fn string passed to fopen is tainted by an environment variable. Using strdup may act as "sanitizing".
Error:TAINTED_STRING is warning that (as far as Coverity can tell) some aspect of the behaviour is influenced by some external input and that the external input is not examined for 'safeness' before it influences execution.
In this particular example it would appear that Coverity is wrong because the value of LOG_FILE is "/log/test%d.log" and is used with an int in the snprintf, meaning that the content of char fn[100] is always well defined.
So a reasonable course of action would be to mark the error as a non-issue so that it is ignored on future runs.
Coverity wants to make sure you sanitize any string which is coming from outside of your program, be it getenv, argv, or from some file read.
You may have a function to sanitize the input(Tainted string) and have a comment provided by Coverty which tells Coverty that input string is sanitized and the SA warning will go away.
// coverity[ +tainted_string_sanitize_content : arg-0 ]
int sanitize_mystring(char* s)
{
// Do some string validation
if validated()
return SUCCESS;
else
return FAILED;
}
// coverity[ +tainted_string_sanitize_content : arg-0 ] is the line Coverty is looking
Hope this helps.

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