Node v8 variable default NULL but reassign based on argument passed - c

I'm sure it's really basic but I haven't been able to find anything like it (perhaps I'm going about it completely the wrong way).. I'm trying to pass str to the 'call_to_c_lib_func' function which takes either NULL or a string (char*).
#include <stdio.h>
#include <string.h>
#include <v8.h>
void test(const v8::FunctionCallbackInfo<Value>& args) {
char *str = NULL;
if (!args[3]->IsNull() && !args[3]->IsUndefined()) {
String::Utf8Value arg_str(args[3]->ToString());
str = *arg_str;
}
// Following function takes either NULL or char*
call_to_c_lib_func(str);
}
Edit: Post originally contained simplified C code for this which didn't really help explain the problem, hopefully this clarifies it a bit.

Your post doesn't ask a question or explain what problem you are having with the code. So I am assuming you ran the code exactly as posted and sometimes the call to the function behaves oddly or crashes.
Your existing code fails because:
String::Utf8Value arg_str(args[3]->ToString());
is inside a { code block } but you try to access its contents after that code block has exited (and therefore after arg_str has been destroyed).
Instead you could write:
String::Utf8Value temp;
char *str = NULL;
if (!args[3]->IsNull() && !args[3]->IsUndefined())
{
temp = args[3]->ToString();
str = *temp;
}
call_to_c_lib_func( str );
Of course there are many ways to skin a cat, just watch out when using v8::String that you do not use the result of operator* after the string has been destroyed, because it returns a pointer to the content of the string.
NB. I'm not familiar with V8 so there may be a more elegant way of accessing args[3]'s string data that neither of us is aware of.

Related

Losing pointer reference to structure member ? (in c)

I am making a little project just for fun about OO in C.
The problem I am encountering is fairly odd to me. The program below is the entire thing.
When compiled and ran, all the 'methods' work properly... up until after it hits the first 'puts'. At this point, the 'methods' have lost the reference to 'self' at this point.
I'm not sure why it works up until then, but not after. It is worth noting that executing the 'constructor' again before the second 'puts' will make it work. The 'if' chains clearly show that the methods work because they properly set the new strings.
I do realize this would be fixed by simply passing the 'object's' address via parameters to the 'methods', but that's kind of the point of the post, I would like to find a neat way to do it without doing so.
#include <stdio.h>
//-----class_a--------------------------------------------------------------//
typedef struct{
char* string;
char* (*get_string)();
char* (*set_string)(char*);
} class_a;
void constructor_class_a(class_a *self, char* string){
self->string = string;
char* get_string(){
return self->string;
} self->get_string = get_string;
char* set_string(char* new_string){
return self->string = new_string;
} self->set_string = set_string;
}
//--------------------------------------------------------------------------//
int main(){
class_a object_a;
constructor_class_a(&object_a, "default string");
printf("string: %s\n", object_a.get_string());
if (object_a.get_string()=="default string"){
object_a.set_string("temporary string");
if (object_a.get_string()=="temporary string"){
object_a.set_string("final string");
if (object_a.get_string()=="final string"){
printf("string: %s\n", object_a.get_string());
}
}
}
printf("%s", object_a.get_string());
return 0;
}
I've tried doing this to no avail (including a int init member to the 'class'):
char* get_string(){
static class_a *self2 = {0};
if (!self2->inti){
*self2 = *self;
self2->init = 1;
}
return self2->string;
} self->get_string = get_string;
The problem is that you're trying to use nested functions, which are not part of the C language but a GCC extension, but using them incorrectly. Their lifetimes end at the end of the block they're nested in, and any use of a function pointer to them after their lifetime ends has undefined behavior.
Even if this did work, it would be an awful idea, since the ability to have pointers to nested functions necessarily depends on having an executable stack, which is deprecated because it makes most kinds of vulnerabilities trivial to exploit. This is among the many reasons that clang and other compilers refuse to copy this GCC feature and why it's essentially dead.

Check if a pointer to function is initialized

How can I check if a pointer to function was initialized?
I can check for NULL, but if not null could be garbage, right?
I have the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct client_struct
{
char *name;
char *email;
void (*print)(struct client_struct *c);
} client;
void print_client(client *c)
{
if (c->print != NULL)
c->print(c);
}
int main()
{
client *c = (client *)malloc(sizeof(client));
c->email = (char *)malloc(50 * sizeof(char));
sprintf(c->email, "email#server.com");
c->name = (char *)malloc(50 * sizeof(char));
sprintf(c->name, "some name");
//Uncommenting line below work as expected, otherwise segmentation fault
//c->print = NULL;
print_client(c);
printf("\nEOF\n");
int xXx = getchar();
return 0;
}
How can I check if this pointer really points to function "void (*f)(client *)"?
Comparing size doesn't work because could garbage in same size, correct?
I would like a way to accomplish that preferably according to C standard.
As described in the comments, it is impossible to determine with 100% certainty whether a pointer is garbage.
To avoid such situation, you can provide a "constructor" function, like this:
struct client_struct* client_allocate()
{
struct client_struct* object = malloc(sizeof *object);
if (object)
{
object->name = NULL;
object->email = NULL;
object->print = NULL;
}
return object;
}
Then write in your documentation that the only valid way to create "clients" is by using your function. If you do this, you should also provide a destroy function, where you call free.
Suppose you add a new pointer to your struct one day. Then you update your client_allocate function, where you set this pointer to NULL, and the new pointer will always be properly initialized. There is no need to update all places in code where your struct is allocated, because now there is only one such place.
Caveats
Checking if a pointer to a function is initialized with an valid function is not an easily solvable problem. Any solution, will not be portable across platforms, and is also dependent on the binary format (statically or dynamically linkable formats) that you end up with. There are ways to do this, with varying success, on different binary formats, however I am not going to go over every permutation. Hopefully this will get you going down that rabbit hole :-) and you can figure out the particular solution that works for you in your circumstances.
In order for some of the solutions to work you have to ensure that the linked binaries have exported symbols (it's possible to do it without, but it's a lot harder and I don't have the time). So when you're linking your program ensure that you have dynamic symbols enabled.
Having said that, here's an approach you can use on systems using dlfcn functions. (See History below)
More Caveats
As #Deduplicator points out in his comment below, there may be situations where 0xdeadbeef may arbitrarily happen to point to a valid function, in which case you may end up with a situation where you end up calling the wrong valid function. There are ways to mitigate that situation at either compile-time or runtime but you'll have to build the solution by hand. For example, C++ does it by mangling in namespace into the symbols. You could require that to happen. (I'll think of an interesting way to do this and post it)
Linux / SysV variants (Mac OSX included)
Use dladdr (SysV) (GNU has a dladdr1 as well) to determine which function does the address you provide fall within:
Example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
int is_valid_function_ptr( void *func) {
Dl_info info;
int rc;
rc = dladdr(func, &info);
if (!rc) {
/* really should do more checking here */
return 0;
}
return 1; /* you can print out function names and stuff here */
}
void print(const char *value) {
fprintf(stdout, "%s", value);
}
void call_the_printer(void (*foo)(), const char *value)
{
if(is_valid_function_ptr(foo)) {
foo(value);
}
else {
fprintf(stderr, "The Beef is Dead!\n");
}
}
int main()
{
void (*funcptr)() = (void (*)()) 0xdeadbeef; /* some dead pointer */
call_the_printer(funcptr, "Hello Dead Beef\n");
funcptr = print; /* actually a function */
call_the_printer(funcptr, "Hello Printer\n");
return 0;
}
NOTE Enable dynamic symbols for this to work
GCC/LLVM etc.
use -rdynamic or -Wl,--export-dynamic during the link process, so compile with:
gcc -o ex1 -rdynamic ex1.c
Windows
Windows does its own thing (as always) and I haven't tested any of these, but the basic concept should work:
Use GetModuleHandle and EnumCurrentProcess together to get loaded symbol information and run through the pointers in a loop to see they match any of the address therein.
The other way would be to use VirtualQuery and then cast mbi.AllocationBase to (HMODULE) and see if you get the path of your own binary back.
In c function pointers are no different than regular pointers and by standard they have one value that says the value should not be used and this is NULL.
The way you should work with pointers is to set them only to valid value or NULL. There is no other way you can be sure there is a OK value. And by definition every value that is not NULL should be considered valid.
Like pointed to in other comments and answers, there is not way to check a variable is initialized. That's why initializing vars to NULL and then checking is considered good practice.
If you really want to validate your function pointer is pointing to the correct place, you could export the function and load your pointer from the ELF symbols (see: http://gcc.gnu.org/wiki/Visibility)
Always check for null parameters first of all.
void print_client(client *c)
{
if ((c != NULL) && (c->print != NULL))
{
c->print(c);
}
}
As for your question, nullify your client struct after it's been malloc'd. This way you can ensure that an unassigned function pointer shall indeed ==NULL.
client* create_client(void)
{
client *c = malloc(sizeof(client));
if (c != NULL)
{
memset(c, 0, sizeof(c))
}
return c;
}

C Program crash "No source available for "0xb7e88a81"" on malloc line (Eclipse)

I have a function that takes a string and cuts out a some parts of it.
The function does its thing a couple of times until, all of a sudden, the same malloc line that worked fine, crashes with No source available for "0xb7e88a81" error.
Tried to clear out every thing to make sure I'm not sending NULL length or whatever, but still no luck.
It worked at least once (debugged it) but on the second or third iteration it crashes.
char *removeOffsetFromLabel (char *label) {
char* labelWithoutOffset;
int i;
labelWithoutOffset = malloc(strlen(label));
........
The crash happens on the malloc line (when trying to move to the next line).
strlen(label) = 7 (checked it)
Any ideas ? I'm using GCC compiler on Eclipse (Ubuntu).
Per FoggyDay's request this is the whole function:
char *removeOffsetFromLabel (char *label) {
char* labelWithoutOffset;
int i;
labelWithoutOffset = (char*)malloc(strlen(label) + 1);
i = 0;
while (label[i] != '\0' && label[i] != OPENING_BRACKET_ASCII_CODE) {
labelWithoutOffset[i] = label[i];
i++;
}
labelWithoutOffset[i] = '\0';
return labelWithoutOffset;
}
I do free up "labelWithoutOffset" outside of the function before calling it again.
I wish I could mark all of your answers with V sign to indicate it solved the issue since you've been most helpful.
After digging in I made two changes to my code and things seem to be working fine so far:
Removed two "free" commands that were used on an already freed up pointers (dumb mistake)
Added "pointer = NULL" after every free (just to be on the safe side)
Again, I thank all of you for showing me other issues I had in my code.
StackOverflow ROCKS !
1) As already mentioned above, "malloc()" MUST BE "strlen()+1":
char *removeOffsetFromLabel (char *label) {
char* labelWithoutOffset = (char *)malloc(strlen(label)+1);
2) Since this didn't solve the problem, we also need to look at:
a) is "label" valid when we call strlen()?
b) do you have any code that might be overwriting "labelWithoutOffset" somewhere else - after you've allocated it in one call, and before you allocate it again in a different call?
SUGGESTIONS:
a) Add this code (or better, look at "label" in your debugger):
char *removeOffsetFromLabel (char *label) {
fprintf (STDERR, "label=%s\n", label);
fprintf (STDERR, "strlen(label)=%d\n", strlen(label);
char* labelWithoutOffset = (char *)malloc(strlen(label)+1);
b) Post some more code from "removeOffsetFromLabel()" - maybe we can see where the variable might be "getting stepped on".
PS:
If you're feeling ambitious, check out my link to the Valgrind tutorial above it.
But for "quick results", please try suggestions 1) and 2); and let us know how it goes.
if strlen(label) is indeed 7, than it's not strlen() but malloc() itself that crashes.
If malloc() crashes, that probably means malloc()'s internal housekeeping was destroyed earlier/elsewhere (by a pointer gone crazy).
Bugs like this are hard (hardest) to find since you can't tell where they are because the crash is likely happening long after the cause.
You might want to look into Valgrind usage.
Scratch that.
i dont understand whatever function type that is there, but to my knowledge of malloc(); and strings, since label is an array you should send it like this
void funcCall(int *)
main()
{
funcCall(label)
}
funcCall(int funcLabel[])
{
}
hope this helps.

concatenate variable onto another variable

const char *SITE_NAME = "test";
char SITE_ROOT[19];
sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME);
I can't figure out why I'm getting an error of:
error: expected ‘)’ before string constant
Basically I just want to concatenate the variable SITE_NAME onto SITE_ROOT. The error is on the sprintf line. Any ideas?
UPDATE: So the code works if it is inside main(). I had it outside of main() so that I could use those variables inside of functions.
The error looks like it might not be shown in the code but the sprintf should be:
sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME);
EDIT:
Here is my complete test code if that helps at all:
#include <string.h>
#include <stdio.h>
int main()
{
const char *SITE_NAME = "test";
char SITE_ROOT[19];
sprintf (SITE_ROOT, "/var/www/html/%s", SITE_NAME);
printf( "%s\n", SITE_ROOT ) ;
return 0 ;
}
As has been pointed out, the direct problem is that you're trying to call sprintf from outside a function.
You mentioned that you are setting the strings this way because you're using SITE_NAME by itself in addition to concatenating it with the path and you want to only have to change it in one place. This is a good goal, known in some circles as "don't repeat yourself" (often abbreviated DRY). However, even if the code worked (say, because you moved the sprintf call into main), you haven't really achieved your goal due to the following line:
char SITE_ROOT[19];
You are declaring a fixed length array exactly big enough to hold "/var/www/html/test", which is just asking for a buffer overflow. When you change SITE_NAME from "test" to, for example, "someRealSiteName", you'll very probably overwrite something else when you concatenate, causing unpredictable results. So you have to manually recalculate the length of the final string and update the array size (which would be easy to get wrong, say by forgetting to add 1 for the null terminator) every time you change SITE_NAME.
You could, of course, limit the length of SITE_NAME and size SITE_ROOT to hold the longest possible path, but it'd be an artificial limit and you might end up wasting space. Furthermore, you'd still have to verify the length isn't exceeded at run-time (or use a function that will ignore extra characters).
Instead, you could dynamically set the size of SITE_ROOT like so:
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
const char SITE_PATH[] = "/var/www/html/";
const char SITE_NAME[] = "someRealSiteName";
char *SITE_ROOT = NULL; // just making this explicit, would be set to 0 anyway
int main(void)
{
size_t siteRootLength = strlen(SITE_PATH) + strlen(SITE_NAME);
SITE_ROOT = malloc(siteRootLength + 1); //don't forget to account for the terminating '\0'
strcpy(SITE_ROOT, SITE_PATH);
strcat(SITE_ROOT, SITE_NAME);
printf("%s\n", SITE_NAME):
printf("%s\n", SITE_PATH):
printf("%s\n", SITE_ROOT):
return 0;
}
This solution is okay, but has some drawbacks:
SITE_ROOT can't be a const pointer , so both the string and the pointer itself could be accidentally changed
Site path and name will each be in memory twice (though it sounds like you're okay with that)
Concatenation is being done at run-time when it could be done at compile-time
Code is longer and more complex than necessary for such a simple task
Risk that SITE_ROOT is used before it has the correct value (or is even a valid pointer/string!) in some other initialization code or another thread.
I feel something like the following is better:
#include <stdio.h>
#define SITE_PATH_MACRO "/var/www/html/"
#define SITE_NAME_MACRO "someRealSiteName"
// the preprocessor will merge the two string literals into one
#define SITE_ROOT_MACRO SITE_PATH_MACRO SITE_NAME_MACRO
// you could do without some or all of these if you don't need them
// (or are willing to use the macros directly)
const char SITE_PATH[] = SITE_PATH_MACRO;
const char SITE_NAME[] = SITE_NAME_MACRO;
const char SITE_ROOT[] = SITE_ROOT_MACRO;
int main(void)
{
printf("%s\n", SITE_NAME);
printf("%s\n", SITE_PATH);
printf("%s\n", SITE_ROOT);
return 0;
}
Since this is a pretty straightforward case, you can simply initialize the string and then concatenate onto it. You might want to add checks to ensure you don't go beyond you string's boundaries though.
strcpy(SITE_ROOT, "/var/www/html/");
strcat(SITE_ROOT, SITE_NAME);

How to make a pointer in a function change the pointee in C

Hee guys,
I have been reading a couple of things about pointers and pointees and started getting curious. The only thing I dont understand is how pointers behave in functions, hence the following code:
#include <stdio.h>
int pointeeChanger(char* writeLocation) {
writeLocation = "something";
return 0;
}
int main(void)
{
char crypted[] = "nothing";
char* cryptedPointer = crypted;
pointeeChanger(cryptedPointer);
printf("The new value is: %s", cryptedPointer);
return 0;
}
What my intention to do is to adjust the pointee, "crypted" var, through a pointer given to a function. The only thing is that it is not working. Could you please explain me what is going wrong in my thought process. I am fairly new to C so my errors could be fairly basic.
Thanks in advance!
Greetings,
Kipt Scriddy
C strings are not the best material to learn pointers, because they are implemented as pointers to char. Let's use int instead:
#include <stdio.h>
void pointeeChanger(int* writeLocation) {
// Using dereference operator "*"
*writeLocation = 42; // something
}
int main(void) {
int crypted = 0; // Nothing
pointeeChanger(&cryptedPointer); // Taking an address with "&"
printf("The new value is: %d", crypted);
return 0;
}
This works as expected.
Modifying strings in place is a lot harder, because you are forced to deal with memory management issues. Specifically, the string into which you copy must have enough space allocated to fit the new string. This wouldn't work with "nothing" and "something", because the replacement is longer by two characters.
Short answer: writeLocation is a local variable and is a copy of cryptedPointer. When you modify writeLocation, cryptedPointer is not modified.
If you want to modify cryptedPointer, you have to pass a pointer to it, like so:
#include <stdio.h>
int pointeeChanger(char** writeLocation) { /* Note: char** */
*writeLocation = "something"; /* Note: *writeLocation */
return 0;
}
int main(void)
{
char crypted[] = "nothing";
char* cryptedPointer = crypted;
pointeeChanger(&cryptedPointer); /* Note: &cryptedPointer */
printf("The new value is: %s", cryptedPointer);
return 0;
}
There are other issues with this code though. After the call to pointeeChanger(), cryptedPointer no longer points to the crypted array. I suspect you actually wanted to change the contents of that array. This code fails to do that.
To change the value of crypted[] you will need to use strcpy() or (preferably) strncpy(). Also you will need to watch the size of the crypted[] array - "something" is longer than "nothing" and will cause a buffer overflow unless crypted[] is made larger.
This code will modify the original crypted[] array:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 64
/*
* Only char* required because we are not modifying the
* original pointer passed in - we are modifying what it
* points to.
*/
int pointeeChanger(char* writeLocation)
{
/*
* In C, you need to use a function like strcpy or strncpy to overwrite a
* string with another string. Prefer strncpy because it allows you to
* specify a maximum size to copy, which helps to prevent buffer overruns.
*/
strncpy(writeLocation, "something", MAX_STR_LEN);
/* strncpy doesn't automatically add a \0 */
writeLocation[MAX_STR_LEN] = '\0';
return 0;
}
int main(void)
{
/*
* The +1 is because an extra character is required for the
* null terminator ('\0')
*/
char crypted[MAX_STR_LEN + 1] = "nothing";
pointeeChanger(crypted);
printf("The new value is: %s", crypted);
return 0;
}
It depends slightly on what you actually want to do:
Do you want to change what cryptedPointer is pointing to, or change the content that cryptedPointer is pointing at?
The second can be done by:
strcpy(writeLocation, "something");
Beware that if something is longer than what the original string's size, you'll overflow the buffer, which is a bad thing. So to fix this, you'd have to have char crypted[10] = "nothing";, to make space for the string "something".
You can clearly also do something like:
writeLocation[2] = 'f';
writeLocation[3] = 'f';
and have the printf print "noffing"
but if you want to do the first variant, then you need to pass a pointer to the pointer:
int pointeeChanger(char** writeLocation) {
*writeLocation = "something";
return 0;
}
And then call:
pointeeChanger(&cryptedPointer);
Note that when this returns, cruptedPointer is pointing at a constant string that can't be modified, where your original crypted can be modified.
Consider that Tom is hired by Sally to break knuckles for the mafia.
Pass-by-value: If Sally tells Tom to count the number of knuckles he breaks at work today, then Sally has no way of knowing which number Tom has come up with until he returns from the road. They both have a copy of the number "zero" in their heads to begin with, but Tom's number might increase throughout the course of the day.
Note the word "copy". When you pass-by-value to a function, you're passing a copy of the object. When you modify the object within a function, you're modifying the copy instead of the original.
Pass-by-reference: If Sally tells Tom to tally the number of knuckles he breaks in the sky, then she (and anyone else who's interested) can refer to the sky. By changing the sky, Tom would also be changing Sally's number.
edit: C doesn't have pass-by-reference, though it does have pointers, which are reference types. Passing a pointer is still pass-by-value, and a copy with the same pointer value is still formed. Hence, your assignment is to the copy, not the original.

Resources