Segmentation fault with strcpy (ELF executable) - c

I know there is a BoF in the program, but the buffer is not exceded with "AA", then, why I obtain "segmentation fault"?...
$ gcc program.c -o program
$ ./program AA
Segmentation fault
This is the source:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(char *arg)
{
char name[32];
strcpy(name, arg);
printf("\nWelcome, %s\n\n", name);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Use: %s YOUR_NAME\n", argv[0]);
exit(0);
}
func(argv[2]);
printf("The end\n\n");
return 0;
}

You dereference a null pointer. argv[argc] is defined as being NULL.
I think you meant func( argv[1] ); . Arrays index from zero in C.

Related

How to parse json using sscanf in C?

I have the following string in the form of json:
{"num":1,"data":{"city":"delhi"}}
I need to get the value of "num" key using sscanf. Here is my attempt. I know it's incorrect. But I don't know how to do it.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *str = "{\"num\":1,\"data\":{\"city\":\"delhi\"}}";
char *ret = malloc(sizeof(char) * 10);
sscanf(str, "{\"num\":%s, %s" , ret);
printf("%s", ret);
return 0;
}
Any suggestions?
sscanf(str, "{\"num\":%s, %s" , ret);
is wrong, first you have two "%s" but you give only one location to save string (ret), and it does not extract as you expect
you want
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *str = "{\"num\":1,\"data\":{\"city\":\"delhi\"}}";
char *ret = malloc(10); /* by definition sizeof(char) is 1 */
if (sscanf(str, "{\"num\":%9[^,]" , ret) == 1)
printf("value is '%s'\n", ret);
free(ret);
return 0;
}
Compilation and execution
/tmp % gcc -Wall p.c
/tmp % ./a.out
value is '1'
/tmp %
but to use scanf to parse is limited

Segmentation fault in C (beginner)

I'm a newbie in C programming and having pretty simple code here.
It compiles but won't run and a segmentation fault appears. I was looking for hours what could be wrong. Now I have a pretty good idea what segmentation fault means but not why it shows up in my small piece of code:
It's supposed to print out the user_id and group_id of the given parameter.
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
int main(int argc, char *argv[]){
if(argc != 1){
printf("ERROR");
}
struct passwd str;
struct passwd *pointer = getpwnam(argv[1]);
str = *pointer;
printf("user: %d /ngroup: %d",str.pw_uid, str.pw_gid);
return 0;
}
You should check pointer != NULL before assign it into str.
getpwnam() return NULL in case no entry was found or an error occurred. See https://linux.die.net/man/3/getpwnam for more detail.
I can detect some problems here:
Check if number of arguments is greater than 0, otherwise exit your program
You should check if return value from getpwnamreturns NON-NULL value.
I would rewrite this to:
int main(int argc, char *argv[]){
struct passwd str;
struct passwd *pointer;
//Number of arguments check
if (argc <= 1) {
printf("ERROR");
exit(0);
}
pointer = getpwnam(argv[1]);
if (pointer) {
str = *pointer;
printf("user: %d /ngroup: %d\r\n",str.pw_uid, str.pw_gid);
printf("user: %d /ngroup: %d\r\n", pointer->pw_uid, pointer->pw_gid);
}
return 0;
}
You probably want this:
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
int main(int argc, char *argv[]){
if(argc < 2){
printf("usage: %s username", argv[0]);
return 1;
}
struct passwd *pointer = getpwnam(argv[1]);
if (pointer == NULL) {
printf("user: %s does not exist\n", argv[1]);
return 1;
}
printf("uid: %d\ngroup: %d\n", pointer->pw_uid, pointer->pw_gid);
return 0;
}
You need to check if getpwnam returns NULL. If yes, that means that the user does not exist and dereferencing a NULL pointer results in undefined behaviour (usually a seg fault).
BTW: the variable struct passwd str is not needed, you can access pointer directly.

Sprintf with pointers, constants and string formatting

I am new to C and I have had trouble simplifying this program. I am trying to initalize name once and strcat name to command once. It is a command line executable that takes two args and one optional arg for the filename "new py" or "new txt", or "new py script". I run Windows's MinGW to compile.
Is there a type to allow storage of argv value and a string constant with one line?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char command[100] = "cd . > ";
char *type = argv[1];
char * name;
strcat(command,"\"");
if (argc == 3) {
char * name = argv[2];
//strcat(command,name);
} else {
char name[20];
sprintf(name,"new %s file",type);
//strcat(command,str);
}
strcat(command,name);
strcat(command,".");
strcat(command,type);
strcat(command,"\"");
system(command);
return 0;
}
As mentioned by BLUEPIXY, my block needs to include "char name[20]; if(argc == 3){ strcpy(name, argv[2]); } else { sprintf(name,"new %s file",type); } strcat(command, name);". After those changes, I converted all of the strcats to one sprinf.
My previous understanding of storing argv items was that char pointers were needed for compilation because args wouldn't be defined. They are not needed any more because of the initialization of name.
My now condensed code is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char command[100];
char * type = argv[1];
char name[50];
if (argc == 3) {
strcpy(name, argv[2]);
} else {
sprintf(name,"new %s file",type);
}
sprintf(command,"cd . > \"%s.%s\"",name,type);
system(command);
return 0;
}
Again, thank you BLUEPIXY for clearing my misunderstanding.

how do "system()" without message on stderr on SunOS

I'm trying to figure out how to do a system() function call (in C) on SunOS and NOT have anything printed to stderr (or stdout). Currently, the following code compiles/runs on Linux, OSX, HP-UX, and SunOS. On all but SunOS, I get a nice output of something like:
i = 32512 (0x7f00); wexitstatus = 127
But, on SunOS I get:
sh: unknowncommand: not found
i = 256 (0x100); wexitstatus = 1
...that extra "sh:" line is annoying :)
(My goal: quiet programmatic determination of whether or not I can do "cc" and/or "gcc" commands.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char **argv)
{
int i;
char buf [1000];
strcpy (buf, "unknowncommand -c foo.c > /dev/null 2>&1");
i = system (buf);
printf ("i = %d (0x%x); wexitstatus = %d\n", i, i, WEXITSTATUS (i));
return 0;
}
The which command will find an executable that lives in your PATH variable.
which gcc
which cc
you can use this in your system call.
This is a poor man's version of which:
// performs task similar to which command
// mywhich.c
char **split(char **result, char *w, const char *src, const char *delim)
{
char *p;
w=strdup(src);
int i=0;
for(p=strtok(w, delim); p!=NULL; p=strtok(NULL, delim))
{
result[i++]=p;
result[i]=NULL;
}
return result;
}
char *detect_cc(char *cc, char **argv)
{
char search[PATH_MAX]={0x0};
char resolved[PATH_MAX]={0x0};
char *w=NULL;
int i=0,j=0;
char *result[1024]={NULL}; // set 1024 to appropriate value
char *PATH=getenv("PATH");
*cc=0x0;
split(result, w, PATH, ":");
for(i=0 ; !*cc && result[i]!=NULL; i++)
{
for(j=0; argv[j]!=NULL; j++)
{
sprintf(search,"%s/%s", result[i], argv[j]);
if(realpath(search, resolved)!=NULL)
{
if(access(resolved, X_OK)==0)
strcpy(cc, resolved);
}
}
}
free(w);
return cc;
}
int main(int argc, char **argv)
{
char cc[PATH_MAX]={0x0};
argv++;
detect_cc(cc, argv);
if(*cc)
printf("found: %s\n", cc);
else
printf("Not found in PATH\n");
return 0;
}
usage:
./mywhich gcc cc foo
It stops on the first file found. Doctor the code to suppress messages as you see fit.
You could use popen() instead of system() and explicitly capture the output of the process.
Here is one simple way to drop the output:
strcpy (buf, "sh -c 'unknowncommand -c foo.c' > /dev/null 2>&1");
i = system (buf);

Iterate through char array and print chars

I am trying to print each char in a variable.
I can print the ANSI char number by changing to this printf("Value: %d\n", d[i]); but am failing to actually print the string character itself.
What I am doing wrong here?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int len = strlen(argv[1]);
char *d = malloc (strlen(argv[1])+1);
strcpy(d,argv[1]);
int i;
for(i=0;i<len;i++){
printf("Value: %s\n", (char)d[i]);
}
return 0;
}
You should use %c format to print characters in C. You are using %s, which requires to use pointer to the string, but in your case you are providing integer instead of pointer.
The below will work. You pass in the pointer to a string when using the token %s in printf.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int len = strlen(argv[1]);
char *d = malloc (strlen(argv[1])+1);
strcpy(d,argv[1]);
printf("Value: %s\n", d);
return 0;
}

Resources