Why copying data into buffer using memcpy cause buffer to overflow? - c

I have this function and once in a while it causes a buffer overflow error at the line in bold which is memcpy(&(sin6->sin6_addr), &(inet->address[0]), 16);
Tried executing this function outside of the application, it never caused an issue. What do you all think why would an app crash at this call?
struct mariyo_inet {
uint8_t length; /* Generally 4 or 16- the length of the address, in bytes. */
uint8_t netmask; /* The number of significant bits in the address. */
uint8_t address[16]; /* The address itself. */
} __attribute__((packed));
void mariyo_inet_to_sockaddr(struct mariyo_inet *inet, struct sockaddr *sock, socklen_t *len, uint16_t port_ne)
{
if (inet->length == 16) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sock;
sin6->sin6_family = AF_INET6;
sin6->sin6_port = port_ne;
#ifndef __linux__
sin6->sin6_len = sizeof(*sin6);
#endif
if (len) *len = sizeof(*sin6);
**memcpy(&(sin6->sin6_addr), &(inet->address[0]), 16);**
} else if (inet->length == 4) {
struct sockaddr_in *sin = (struct sockaddr_in *) sock;
sin->sin_family = AF_INET;
sin->sin_port = port_ne;
#ifndef __linux__
sin->sin_len = sizeof (*sin);
#endif
if (len) *len = sizeof(*sin);
memcpy(&(sin->sin_addr),
&(inet->address[0]),
4);
}
}
Here is the application stacktrace,
#7  0x00000000007c94b9 in mariyo_inet_to_sockaddr (inet=inet#entry=0x7ff31a7da940, sock=sock#entry=0x7ff31a7da900, len=len#entry=0x7ff31a7da8f0, port_ne=port_ne#entry=0) at mariyo.c:4959
        sin6 = 0x7ff31a7da900
#8  0x000000000062847a in enzyme_mconn_icmp_transmit_cb () at enzyme_mconn_icmp.c:522
        ret = <optimized out>
        mconn_icmp = <optimized out>
        icmp_buf_len = <optimized out>
        icmp_linear_buf = 0x61d000d6cec8 "E"
        iph = 0x61d000d6cec8
        iph_len = <optimized out>
        icmp_hdr = <optimized out>
        icmpreq_cookie = 0x604000845f68
        icmpinfo = 0x619000355298
        icmpfail_cookie = <optimized out>
        ip_tlen = 1228
#9  0x0000000000603595 in enzyme_mconn_dequeue_data (mconn=mconn#entry=0x624010002b90, need_to_lock=0) at enzyme_mconn.c:547
        ret = 0
        tx_len = 1228
        __FUNCTION__ = "enzyme_mconn_dequeue_data"
#10 0x0000000000608ee5 in enzyme_mconn_send_data_to_client (mconn=mconn#entry=0x624010002b90, buf=buf#entry=0x60e000188218, buf_len=buf_len#entry=1228, need_to_lock=need_to_lock#entry=1) at enzyme_mconn.c:668
        res = 0
        enq_len = <optimized out>
        drop_len = <optimized out>
        __FUNCTION__ = "enzyme_mconn_send_data_to_client"
#11 0x0000000000609b42 in enzyme_client_process_rx_data (mconn=mconn#entry=0x624010003148, buf=buf#entry=0x60e000188218, buf_len=buf_len#entry=1228) at enzyme_mconn.c:952
        peer = 0x624010002b90
        res = <optimized out>
        __FUNCTION__ = "enzyme_client_process_rx_data"
        ip_proto = <optimized out>
This is how it looks at the caller,
int mariyo_string_to_inet(const char *in_str, struct mariyo_inet *inet)
{
char tmp[51];
//
// filling tmp here from in_str
//
/* IPv4 + IPv6 in same address == bad */
if (saw_dot || saw_colon) {
if (saw_colon) {
/* IPv6 (Note: Supports IPv4 in IPv6) */
if (!inet_pton(AF_INET6, tmp, &(inet->address[0]))) {
//fprintf(stderr, "%s:%d: Could not parse IP address <%s>\n", __FILE__, __LINE__, tmp);
return 1;
}
if (!slash) netmask = 128;
if (netmask > 128) {
//fprintf(stderr, "%s:%d: Bad netmask > 128 on IP address <%s>\n", __FILE__, __LINE__, in_str);
return 1;
}
inet->length = 16;
}
return 0;
}
{
.....
socklen_t sock_len;
struct mariyo_inet inet_ip;
struct sockaddr sock_addr;
memset(&inet_ip, 0, sizeof(struct mariyo_inet));
mariyo_string_to_inet(icmpinfo->probe_info.dest_ip, &inet_ip);
memset(&sock_addr, 0, sizeof(struct sockaddr));
mariyo_inet_to_sockaddr(&inet_ip, &(sock_addr), &sock_len, 0);
....
}

struct sockaddr is not guaranteed to be large enough (and usually isn't) to hold an IPv6 address.
Use struct sockaddr_storage instead.

Related

how to use long options in c?

how to use long options via getopt_long:
for example like this:
--wide-option
I have --wide and -w.
And on --wide-option it gives the following error:
"unrecognized option"
int main(int argc, char **argv)
{
    struct option opts[] =
    {
        {"wide", 1, 0, 'w'},
        {
            0, 0, 0, 0
        }
    };
    int option_val = 0;
    int counter = 10;
    int opindex = 0;
    while ((option_val = getopt_long(argc, argv, "w:", opts, &opindex)) != -1)
    {
        switch (option_val)
        {
        case 'w':
            if (optarg != NULL)
                counter = atoi(optarg);
            for (int i = 0; i < counter; i++)
                printf("Hello world\n");
            break;
        default:
            return 0;
        }
    }
    return 0;
}
If you look at the cat source code (here), you can see that --number and --number-nonblank are two different options (-b and -n). (near line 555).
If you want to do the same, you can that way:
#include <getopt.h>
#include <stdio.h>
int main(int argc, char **argv)
{
struct option opts[] =
{
{"wide", 1, 0, 'w'},
{"wide-option", 0, 0, 'o'}, /* declare long opt here */
{
0, 0, 0, 0
}
};
int option_val = 0;
int counter = 10;
int opindex = 0;
while ((option_val = getopt_long(argc, argv, "w:o", opts, &opindex)) != -1) /* the case here (I arbitrary choose 'o') */
{
switch (option_val)
{
case 'w':
if (optarg != NULL)
counter = atoi(optarg);
printf("option --wide %d found!\n", counter);
for (int i = 0; i < counter; i++)
printf("Hello world\n");
break;
case 'o': /* and take the case into account */
printf("option --wide-option found!\n");
break;
default:
return 0;
}
}
return 0;
}

User defined functions in c are not switching

problem
I was making a c program in which users details are accepted checked and added to a file
but while compile the functions are not changing i meant it only asks the name and the program end
can someone please help me out!
#include <string.h>
void main()
void regis_name();
void regis_dob();
void regis_pin();
void check();
//checks code is not added here
{
     int a, i, j, n, b, f = 1, d[1], m[1], y[1], f1 = 1;
    int *a1, *d1[1], *m1[1], *y1[1];
    a1 = a;
    d1[1] = &d[1];
    m1[1] = &m[1];
    y1[1] = &y[1];
    regis_pin();
void regis_name()
{
    char name[3];
    printf("ADD YOUR NAME: \n ");
    scanf("%s", name[3]);
   regis_dob(); // to dob
}
bd
void regis_dob()
{
    int a, i, j, n, b, f = 1, d[1], m[1], y[1], f1 = 1;
    printf("enter date in 'dd' month in 'mm' year in 'yyyy' \n \n");
    printf("enter dd:   \n");
    scanf("%d", &d[1]);
    printf("enter mm:   \n");
    scanf("%d", &m[1]);
    printf("enter yyyy:  \n");
    scanf("%d", &y[1]);
   regis_pin; // to pin
}
void regis_pin()
{
    int a;
    printf("ADD A PASS CODE OF 4 DIGIT:  \n");
    scanf("%d", &a);
    printf("\n");
    check(); // to pin check
}```

Strtok:I dont know why this program keeps failing

In this program the char *token is initialized with a weird garbage value.I am unable to sort it out. Here's the source code:
#include<iostream>
#include<string.h>
#include<stdlib.h>
void fetch_value(char *string,int pos,char *dest)
{
    char *token;
    int i=0;
    token=strtok(string,",");
    if(pos>1)
    {
        token=strtok(NULL,",");
        while(i<pos-1){
            token=strtok(NULL,",");
            printf("token =%s\n",token);
            i++;
        }
        strcpy(dest,token);
    }
    else
    {
        strcpy(dest,token);
    }
}
int main(void)
{
    char checking[100];
    memset(checking,0x00,sizeof(checking));
    fetch_value("14174000100,35679700322,35679700322,35679700322,
            35679700322,14174000999,919440710210000,1",0,checking);
    printf("checking=%s\n",checking);
    return 0;
}
Your help, feedback or suggestions is greatly appreciated.
The first argument of strtok must be modifiable. Your code passes a string literal, which is not modifiable. This leads to undefined behavior.
The simplest modification that will fix the problem is as follows:
char numList[] = "14174000100,35679700322,35679700322,35679700322,35679700322,14174000999,919440710210000,1";
fetch_value(numList, 0, checking);
You should also note that strtok is an older function which is not reentrant, because it uses static variables to save its state. In the new code you should use the reentrant version of the function - strtok_r, which requires you to pass memory for saving the state.
Do this instead:
int main(void)
{
char checking[100];
memset(checking,0x00,sizeof(checking));
char string[] = "14174000100,35679700322,35679700322,35679700322,
35679700322,14174000999,919440710210000,1";
//now string can be modified.
fetch_value(&string[0],0,checking);
printf("checking=%s\n",checking);
return 0;
}

Access element of nested struct

In C, is it possible to have a struct nested within another struct? How would I access the fields of the inner struct? Take the struct for kinfo_proc for example:
struct kinfo_proc {
  struct  extern_proc kp_proc;      /* proc structure */
  struct  eproc {
    struct  proc *e_paddr;    /* address of proc */
    struct  session *e_sess;  /* session pointer */
    struct  _pcred e_pcred;   /* process credentials */
    struct  _ucred e_ucred;   /* current credentials */
    struct   vmspace e_vm;    /* address space */
    pid_t e_ppid;     /* parent process id */
    pid_t e_pgid;     /* process group id */
    short e_jobc;     /* job control counter */
    dev_t e_tdev;     /* controlling tty dev */
    pid_t e_tpgid;    /* tty process group id */
    struct  session *e_tsess; /* tty session pointer */
#define WMESGLEN  7
    char  e_wmesg[WMESGLEN+1];  /* wchan message */
    segsz_t e_xsize;    /* text size */
    short e_xrssize;    /* text rss */
    short e_xccount;    /* text references */
    short e_xswrss;
    int32_t e_flag;
#define EPROC_CTTY  0x01  /* controlling tty vnode active */
#define EPROC_SLEADER 0x02  /* session leader */
#define COMAPT_MAXLOGNAME 12
    char  e_login[COMAPT_MAXLOGNAME]; /* short setlogin() name */
#if CONFIG_LCTX
    pid_t e_lcid;
    int32_t e_spare[3];
#else
    int32_t e_spare[4];
#endif
  } kp_eproc;
};
How would I go about trying to get the e_ppid of a newly made kinfo_proc instance?
You would be creating something like :
struct kinfo_proc test1;
test1.kp_eproc.e_ppid /// Access it like this.

rearranging an array of data without using temporary array

How can I rearrange an array if I know where to put each element in array without using temporary array?
I guess, This has something to do with cyclic permutation but I cannot figure out how they can be linked each other. Wiki page seems irrelevant to me(http://en.wikipedia.org/wiki/Cyclic_permutation)
If you know both where to put each element in the array, and also which element of the array belongs at a specific index, then you can use that information to optimise your rearrangement. Otherwise you can iterate over all the array elements exchanging them into the correct location until they are all correctly placed.
void permuteObjects(Object[] elements, int[] positions)
{
for (int i = 0; i < elements.length; ++i) {
while (positions[i] != i) {
swapObjects(elements, i, positions[i]);
swapIntegers(positions, i, positions[i]);
}
}
}
If you can boil down the "re-arrangement" of your array to single permutations, i.e. to swapping the values of two elements then you can use the XOR to perform the swap without additional variable.
Here a sample code from the linked Wikipedia article:
void xorSwap (int *x, int *y) {
if (x != y) {
*x ^= *y;
*y ^= *x;
*x ^= *y;
}
}
Why not just use a temporary array and terminate it by setting it to null?
Maybe take a look at http://docs.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html
HashMaps dynamicly increase when adding new items.
Use like this:
HashMap<Integer, WhatEverYouWantToStore> = new HashMap<Integer, WhatEverYouWantToStore>();
Maybe try this:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class sort {
        public static void main(String[] args) {
                List list = new ArrayList();
                String country[] = { "India", "Japan", "USA", "UK", "Nepal" };
                for (int i = 0; i < 5; i++) {
                        list.add(country[i]);
                }
                Collections.sort(list);
                Iterator i = list.iterator();
                while (i.hasNext()) {
                        System.out.print(i.next() + "\t");
                }
        }
}

Resources