How to detect buffer overflow in C for this particular case, - c

I think this code should produce a buffer overflow error but apparently, this prints fine.. is there anyway to detect it has overflown?
Valgrind didn't picked it up either...
static void e(void) {
char buffer[5];
char data1[] = "abc";
char data2[] = "de";
memcpy(buffer, data1, sizeof(data1));
// strcat appends data2 to buffer and adds '\0' at the end dest
strcat(buffer, data2);
//printf("%s\n", buffer);
}

The -fsanitize=address of gcc is the option you're looking for. E.g.:
$ cat test.cpp
#include <stdio.h>
#include <string.h>
static void e(void) {
char buffer[5];
char data1[] = "abc";
char data2[] = "de";
memcpy(buffer, data1, sizeof(data1));
// strcat appends data2 to buffer and adds '\0' at the end dest
strcat(buffer, data2);
//printf("%s\n", buffer);
}
int main() {
e();
}
$ g++ test.cpp -o a -fsanitize=address -g3
$ ./a
=================================================================
==21537== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd1d8c0313 at pc 0x7f96ebedd94b bp 0x7ffd1d8c0260 sp 0x7ffd1d8bfa20
WRITE of size 3 at 0x7ffd1d8c0313 thread T0
#0 0x7f96ebedd94a (/usr/lib/x86_64-linux-gnu/libasan.so.0.0.0+0xe94a)
#1 0x40091b (/tmp/a+0x40091b)
#2 0x400959 (/tmp/a+0x400959)
#3 0x7f96ebb2bec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4)
#4 0x400748 (/tmp/a+0x400748)
Address 0x7ffd1d8c0313 is located at offset 163 in frame <e> of T0's stack:
This frame has 3 object(s):
[32, 35) 'data2'
[96, 100) 'data1'
[160, 165) 'buffer'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
0x100023b10010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b10020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b10030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b10040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
0x100023b10050: f1 f1 03 f4 f4 f4 f2 f2 f2 f2 04 f4 f4 f4 f2 f2
=>0x100023b10060: f2 f2[05]f4 f4 f4 00 00 00 00 00 00 00 00 00 00
0x100023b10070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b10080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b10090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b100a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100023b100b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==21537== ABORTING

Related

C hexadecimal formatting giving me extra digits

I've been working on a small program to dump the hex values of a file, similar to od or hexdump, and I've ran into an issue when printing the values. For certain hex values, mostly ones with alphabetical characters as their second digit, it prints with 6 extra f digits before printing the actual number, instead of just printing a 2-width value like I had specified. I have confirmed that the values themselves are not unexpected in any way, it's the printing that's messing it up.
Code:
int main(int argc, char* argv[]) {
FILE* dataFile = fopen(argv[1], "rb");
int byteCount = 0;
char currentByte = fgetc(dataFile);
while (currentByte != EOF) {
printf("%08d", byteCount);
do {
//print as hex
printf(" %02x ", currentByte);
//set up for next loop
currentByte = fgetc(dataFile);
byteCount++;
} while (currentByte != EOF && (byteCount) % 16 != 0);
printf("\n");
}
printf("%08d\n", byteCount);
}
Output:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
00000016 03 00 3e 00 01 00 00 00 10 6b 00 00 00 00 00 00
00000032 40 00 00 00 00 00 00 00 08 23 02 00 00 00 00 00
00000048 00 00 00 00 40 00 38 00 0d 00 40 00 1f 00 1e 00
00000064 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00
00000080 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00000096 ffffffd8 02 00 00 00 00 00 00 ffffffd8 02 00 00 00 00 00 00
00000112 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00
00000128 18 03 00 00 00 00 00 00 18 03 00 00 00 00 00 00
00000144 18 03 00 00 00 00 00 00 1c 00 00 00 00 00 00 00
00000160 1c 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
00000176 01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00
00000192 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000208 fffffff8 34 00 00 00 00 00 00 fffffff8 34 00 00 00 00 00 00
Does anyone know what's going on here?
There are several problems here.
char is entirely unsuitable to hold raw binary data, because it has implementation-defined signedness and it often a signed type, see Is char signed or unsigned by default?. In fact char should only ever be used for text strings. Instead, you would normally use uint8_t. However... :
The EOF constant is of type int, so if you intend to compare something against EOF, it must be type int. fgetc is guaranteed to return characters as if they were unsigned char but converted to int - as it happens, int is large enough to hold all values of an unsigned char so int can be used here.
%x specifier for printf expects an unsigned int.
Fixes:
char currentByte -> int currentByte
printf(" %02x ", currentByte); -> printf(" %02x ", (unsigned int)currentByte);.
You must always check if fopen was successful and also fclose the file pointer when done. Also note that calling fopen directly on argv with no input sanitation is not acceptable in a professional program. You don't even know if argv[1] exists - the program needs a whole lot more error handling overall.

gcc -O2 creates an endless loop, probably because of undefined behaviour

I wrote this C code to solve Advent of Code 13 2020. I know, it's probably not viable trying to solve it via brute force, but the program gives the correct answer for the example input.
If I try to let gcc optimize the code, it gives the correct result with -O1, but creates an endless loop with -O2. After all the research my conclusion is that there is undefined behavior in my code, I guess it has to do with the probability that "found" may never be higher than 0 and so "time" would overflow.
Here is the question: Does anybody know how to patch that undefined behavior?
"-Wall -Wextra -pedantic" don't even issue a warning or something.
I just can't find a solution. If I, for example, change the head of the while loop to (!found && time < 10000000000), so that no overflow can occur, it just breaks the loop right away with a time value of 10000000003 when compiled with -O2, but still gives the right result with -O1.
Here is the code, the correct result would be "1068781":
#include <stdio.h>
int main()
{
unsigned int busses[] = {7, 0, 13, 2, 59, 1, 31, 0, 19};
unsigned int busses_used = 9;
unsigned int i = 0;
unsigned int found = 0;
unsigned long long time = 0;
unsigned int offset = 0;
unsigned int increment = 7;
while (!found) {
time += increment;
offset = 0;
for (i = 0; i < busses_used; i++) {
if ((time + offset) % busses[i] == 0) {
found = 1;
offset++;
} else {
found = 0;
break;
}
offset += busses[++i];
}
}
printf("Endtime: %lld\n", time);
return 0;
}
Edit: Thanks to KamilCuk for pointing out that the code is accessing the array out of bounds and teaching how to find out that it is doing so. The problem is solved by adding another 0 at the end of the "busses" array and therefore also setting "busses_used" to 10 instead of 9.
I do not understand the code and not indent to, but the loop is strange. Anyway:
"-Wall -Wextra -pedantic" don't even issue a warning or something.
And there are also other ways to detect UB! Compiling your code with some more -fsanitize=* options results with:
+ gcc -Wall -Wextra -ggdb3 -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize-address-use-after-scope /tmp/1.c
/tmp/1.c:22:29: runtime error: index 9 out of bounds for type 'unsigned int [9]'
/tmp/1.c:22:29: runtime error: load of address 0x7ffc48c7a894 with insufficient space for an object of type 'unsigned int'
0x7ffc48c7a894: note: pointer points here
13 00 00 00 60 60 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 08 aa c7 48 fc 7f 00 00
^
=================================================================
==73835==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc48c7a894 at pc 0x55c28a5bf773 bp 0x7ffc48c7a800 sp 0x7ffc48c7a7f0
READ of size 4 at 0x7ffc48c7a894 thread T0
#0 0x55c28a5bf772 in main /tmp/1.c:22
#1 0x7f0060bd1151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
#2 0x55c28a5bf12d in _start (/tmp/tmp.qv8ZsZofOJ.out+0x112d)
Address 0x7ffc48c7a894 is located in stack of thread T0 at offset 84 in frame
#0 0x55c28a5bf208 in main /tmp/1.c:3
This frame has 1 object(s):
[48, 84) 'busses' (line 4) <== Memory access at offset 84 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/1.c:22 in main
Shadow bytes around the buggy address:
0x1000091874c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000091874d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000091874e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000091874f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187500: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 f1 f1 00 00
=>0x100009187510: 00 00[04]f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x100009187520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100009187560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==73835==ABORTING
After quick inspection the out of bounds access to busses happens here:
offset += busses[++i];
Does anybody know how to patch that undefined behavior?
No idea, but write an algorithm that doesn't access the array out of bounds.

AF_XDP: `BPF_MAP_TYPE_XSKMAP` only has entries with `Operation not supported`

This is all my XDP / BPF kernel code:
struct bpf_map_def SEC("maps") xsks_map = {
.type = BPF_MAP_TYPE_XSKMAP,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 64, /* Assume netdev has no more than 64 queues */
};
struct bpf_map_def SEC("maps") rx_queue_pckt_counter_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(unsigned long),
.max_entries = 48,
};
SEC("xdp_sock")
int xdp_sock_prog(struct xdp_md *ctx) {
int index = ctx->rx_queue_index;
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
void *pos = data;
struct ethhdr *eth = (struct ethhdr*)(pos);
if(eth + sizeof(struct ethhdr) <= data_end) {
if(bpf_ntohs(eth->h_proto) == ETH_P_IP) {
struct iphdr *iph = (struct iphdr*)(pos + sizeof(struct ethhdr));
if(iph + sizeof(struct iphdr) <= data_end) {
if(iph->protocol == IPPROTO_UDP) {
const __u16 iph_sz_in_bytes = iph->ihl * 4;
if(iph + iph_sz_in_bytes <= data_end) {
struct udphdr *udh = (struct udphdr*)(pos + sizeof(struct ethhdr) + iph_sz_in_bytes);
if(udh + sizeof(struct udphdr) <= data_end) {
void *rec = bpf_map_lookup_elem(&rx_queue_pckt_counter_map, &index);
if(rec) {
long *pckt_counter_val = (long*)(rec);
*pckt_counter_val += 1;
} else {
return XDP_PASS;
}
if (bpf_map_lookup_elem(&xsks_map, &index)) {
const int ret_val = bpf_redirect_map(&xsks_map, index, 0);
bpf_printk("RET-VAL: %d\n", ret_val);
return ret_val;
}
}
}
}
}
}
}
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
I am trying to filter all IP-UDP packets and send them into user-space. I also count the number of packets arriving for each RX-Queue (indicated by ctx->rx_queue_index).
My program compiles fine but for whatever reason I don't receive any packets in my user-space program. I already talked about this in another post of mine: AF_XDP: No packets from multicast although steered on RX-Queue 0
I executed sudo ethtool -N eth20 flow-type udp4 action 0 beforehand to steer all packets onto RX-Queue 0.
I can see all bpf maps currently active via
$ sudo bpftool map list
32: lpm_trie flags 0x1
key 8B value 8B max_entries 1 memlock 4096B
33: lpm_trie flags 0x1
key 20B value 8B max_entries 1 memlock 4096B
34: lpm_trie flags 0x1
key 8B value 8B max_entries 1 memlock 4096B
35: lpm_trie flags 0x1
key 20B value 8B max_entries 1 memlock 4096B
36: lpm_trie flags 0x1
key 8B value 8B max_entries 1 memlock 4096B
37: lpm_trie flags 0x1
key 20B value 8B max_entries 1 memlock 4096B
125: array name rx_queue_pckt_c flags 0x0
key 4B value 8B max_entries 48 memlock 4096B
126: xskmap name xsks_map flags 0x0
key 4B value 4B max_entries 64 memlock 4096B
But I think only 125 and 126 are related to my program.
The queue-steering works because with sudo bpftool map dump id 125 I get:
key: 00 00 00 00 value: 99 1a cc 04 00 00 00 00
key: 01 00 00 00 value: 00 00 00 00 00 00 00 00
key: 02 00 00 00 value: 00 00 00 00 00 00 00 00
key: 03 00 00 00 value: 00 00 00 00 00 00 00 00
key: 04 00 00 00 value: 00 00 00 00 00 00 00 00
key: 05 00 00 00 value: 00 00 00 00 00 00 00 00
key: 06 00 00 00 value: 00 00 00 00 00 00 00 00
key: 07 00 00 00 value: 00 00 00 00 00 00 00 00
key: 08 00 00 00 value: 00 00 00 00 00 00 00 00
key: 09 00 00 00 value: 00 00 00 00 00 00 00 00
key: 0a 00 00 00 value: 00 00 00 00 00 00 00 00
key: 0b 00 00 00 value: 00 00 00 00 00 00 00 00
key: 0c 00 00 00 value: 00 00 00 00 00 00 00 00
key: 0d 00 00 00 value: 00 00 00 00 00 00 00 00
key: 0e 00 00 00 value: 00 00 00 00 00 00 00 00
key: 0f 00 00 00 value: 00 00 00 00 00 00 00 00
key: 10 00 00 00 value: 00 00 00 00 00 00 00 00
key: 11 00 00 00 value: 00 00 00 00 00 00 00 00
key: 12 00 00 00 value: 00 00 00 00 00 00 00 00
key: 13 00 00 00 value: 00 00 00 00 00 00 00 00
key: 14 00 00 00 value: 00 00 00 00 00 00 00 00
key: 15 00 00 00 value: 00 00 00 00 00 00 00 00
key: 16 00 00 00 value: 00 00 00 00 00 00 00 00
key: 17 00 00 00 value: 00 00 00 00 00 00 00 00
key: 18 00 00 00 value: 00 00 00 00 00 00 00 00
key: 19 00 00 00 value: 00 00 00 00 00 00 00 00
key: 1a 00 00 00 value: 00 00 00 00 00 00 00 00
key: 1b 00 00 00 value: 00 00 00 00 00 00 00 00
key: 1c 00 00 00 value: 00 00 00 00 00 00 00 00
key: 1d 00 00 00 value: 00 00 00 00 00 00 00 00
key: 1e 00 00 00 value: 00 00 00 00 00 00 00 00
key: 1f 00 00 00 value: 00 00 00 00 00 00 00 00
key: 20 00 00 00 value: 00 00 00 00 00 00 00 00
key: 21 00 00 00 value: 00 00 00 00 00 00 00 00
key: 22 00 00 00 value: 00 00 00 00 00 00 00 00
key: 23 00 00 00 value: 00 00 00 00 00 00 00 00
key: 24 00 00 00 value: 00 00 00 00 00 00 00 00
key: 25 00 00 00 value: 00 00 00 00 00 00 00 00
key: 26 00 00 00 value: 00 00 00 00 00 00 00 00
key: 27 00 00 00 value: 00 00 00 00 00 00 00 00
key: 28 00 00 00 value: 00 00 00 00 00 00 00 00
key: 29 00 00 00 value: 00 00 00 00 00 00 00 00
key: 2a 00 00 00 value: 00 00 00 00 00 00 00 00
key: 2b 00 00 00 value: 00 00 00 00 00 00 00 00
key: 2c 00 00 00 value: 00 00 00 00 00 00 00 00
key: 2d 00 00 00 value: 00 00 00 00 00 00 00 00
key: 2e 00 00 00 value: 00 00 00 00 00 00 00 00
key: 2f 00 00 00 value: 00 00 00 00 00 00 00 00
Found 48 elements
As you can see, only the counter for RX-Queue 0 is greater than 0.
But, if I take a look at the BPF_MAP_TYPE_XSKMAP (which is used to transfer packets into user-space), I get:
$ sudo bpftool map dump id 126
key:
00 00 00 00
value:
Operation not supported
key:
01 00 00 00
value:
Operation not supported
key:
02 00 00 00
value:
Operation not supported
key:
03 00 00 00
value:
Operation not supported
key:
04 00 00 00
value:
Operation not supported
...
key:
3e 00 00 00
value:
Operation not supported
key:
3f 00 00 00
value:
Operation not supported
Found 0 elements
Is the message Operation not supported an indicator why I don't receive any packets in my user-space program? Or is it just not possible to receive the value during runtime? I also find it strange to see Found 0 elements.
Any ideas what is wrong here?
This is simply because maps of type BPF_MAP_TYPE_XSKMAP do not support lookup from user space (you'd get addresses from kernel space, which does not make sense from user space point of view and might be a security issue).
So because attempting the lookup returns -EOPNOTSUPP, bpftool is unable to show the values. It could error out and print nothing, but instead we made it print the keys it finds, and print the error messages we get for the values.
As for the Found 0 elements, the count is for the elements that bpftool could retrieve without any error, so it's only logical that it remains at zero in this case.
So nothing seems wrong in your case, I do not believe this output is related to your issue with the missing packets.

Linker adds extra padding in section?

I am using GCC and am trying to get the linker to create an array of data objects from different files in a custom section. I have added this section to the linker script:
.mydata :
{
__mydata_start = .;
KEEP (*(.mydata))
__mydata_end = .;
}
Here is my data structure:
struct my_type_t {
unsigned char a;
size_t b;
void *c;
const void *d;
const void *e;
const char *f;
};
I am on a 64-bit platform, and sizeof(struct my_type_t) gives 48. However, the linker seems to want to align these structures to 64-bytes.
My declarations:
struct my_type_t a1 __attribute__((section(".mydata"))) = {
1, 2, (void *)3, (void *)4, (void *)5, (void *)6,
};
struct my_type_t a2 __attribute__((section(".mydata"))) = {
7, 8, (void *)9, (void *)10, (void *)11, (void *)12,
};
Linker output:
$ gcc -o ldtest ldtest.c -Wl,-Tlink.ld
$ objcopy -Obinary -j .mydata ldtest mydata
$ hd mydata
00000000 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
00000010 03 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000020 05 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 07 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000050 09 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 |................|
00000060 0b 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |................|
If I instead declare it as an array:
struct my_type_t a1[2] __attribute__((section(".mydata"))) = {
{
1, 2, (void *)3, (void *)4, (void *)5, (void *)6,
},
{
7, 8, (void *)9, (void *)10, (void *)11, (void *)12,
},
};
There is no padding, as expected:
00000000 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
00000010 03 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000020 05 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 |................|
00000030 07 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000040 09 00 00 00 00 00 00 00 0a 00 00 00 00 00 00 00 |................|
00000050 0b 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |................|
Why is the linker adding extra padding beyond what the compiler thinks is necessary, and how can I get rid of it?
I don't know why it wants it aligned on 64-byte, but you can do:
struct my_type_t {
unsigned char a;
size_t b;
void *c;
const void *d;
const void *e;
const char *f;
} __attribute__ ((aligned (64)));
To make gcc automatically pad each struct to the nearest higher 64-byte address and make sizeof(struct my_type_t) also include the padding. This makes operations like this work correctly:
struct my_type_t *s = &__mydata_start;
s++; // Jump to next entry
s[0]; // First entry
s[1]; // Second entry

Inexplicable Segmentation fault:11

I have this code below to implement maximum subsequence length searching. I couldn't check if the program is right or not since running my program produces segmentation faults.
The program compiles fine.
Please tell me what I am doing wrong here:
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int a[6]={1,-2,4,33,0,-6}; //THE ACTUAL SEQUENCE
int count_a[6]={1,1,1,1,1,1}; //ARRAY TO KEEP COUNT OF MAXIMUM LENGTHS FROM POINT OF VIEW OF EACH ELEMENT OF ARRAY A
int i=0;
int j=0;
int k=0;
for(k=1;k<6;k++)
{
j=k;
printf("k's value:%d\t",j); //JUST FOR TESTING
while(1)
{
if(a[i]<a[j])
{
if(count_a[j]<(1+count_a[i]))
{
count_a[j]=1+count_a[i];
}
}
if(j-1==1)
{
break;
}
else
{
i++;
}
}
i=0;
}
/* THIS IS FOR ME TO CHECK WHETHER THE LENGTH VALUES HAVE BEEN UPDATED IN THE COUNT_A ARRAY*/
for(k=0;k<6;k++)
{
printf("%d\t",count_a[k]);
}
return 0;
}
You are having infinite loop. j=k; then while(1) can only terminate when if(j-1==1). On the first iteration k is set to 1 so j is also set to 1. Never breaks because 1-1!=1. Your j is never changed inside while(1) loop.
i++ is always the option. When i becomes large it tries to read from outside of array count_a[i] causing segfault.
Let's use clang's address sanitizer to figure out what is going on:
[3:41pm][wlynch#watermelon /tmp] clang -g -fsanitize=address blah.c
[3:41pm][wlynch#watermelon /tmp] ./a.out
=================================================================
==22763==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff52950958 at pc 0x00010d2b0953 bp 0x7fff52950910 sp 0x7fff52950908
READ of size 4 at 0x7fff52950958 thread T0
#0 0x10d2b0952 in main blah.c:20
#1 0x7fff851205ac in start (/usr/lib/system/libdyld.dylib+0x35ac)
#2 0x0 (<unknown module>)
Address 0x7fff52950958 is located in stack of thread T0 at offset 56 in frame
#0 0x10d2b072f in main blah.c:8
This frame has 2 object(s):
[32, 56) 'a' <== Memory access at offset 56 overflows this variable
[96, 120) 'count_a'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow blah.c:20 main
Shadow bytes around the buggy address:
0x1fffea52a0d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1fffea52a120: 00 00 00 00 f1 f1 f1 f1 00 00 00[f2]f2 f2 f2 f2
0x1fffea52a130: 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x1fffea52a140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1fffea52a170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==22763==ABORTING
k's value:1 Abort
So you're accessing beyond the end of a[].
If I reduce your code down, we can see that this is obviously possible:
k = 1;
j = k;
while(1)
{
if(a[i]<a[j])
if(count_a[j]<(1+count_a[i]))
count_a[j]=1+count_a[i];
if(j-1==1)
break;
else
i++;
}
Note that j-1 will never equal 1 on this iteration (it will always be 0), so you will increment i until it is well past the end of a.

Resources