In my C code I call assembly (NASM x86_64) function (main.c).
In assembly I call C function (printf.asm)
That function prints float using printf. (c_printf.c)
I'm getting segfault.
Should I compile/link in another way? Maybe the way I call C function from assembly is incorrect?
I compile with:
gcc -c c_printf.c
nasm -f elf64 -F dwarf -g printf.asm
gcc -o main printf.o c_printf.o main.c
My code:
main.c
extern void start_asm(void);
int main(void) {
start_asm();
return 0;
}
printf.asm
global start_asm
extern printf_float
start_asm:
call printf_float
ret
c_printf.c
#include <stdio.h>
void printf_float(void) {
printf("%f\n", 42.0f);
}
Maybe valgrind output will be helpful?
==16257== Memcheck, a memory error detector
==16257== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==16257== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==16257== Command: ./main
==16257==
--16257-- WARNING: Serious error when reading debug info
--16257-- When reading debug info from /home/starsep/stack/main:
--16257-- Overrun whilst parsing .debug_abbrev section(2)
==16257==
==16257== Process terminating with default action of signal 11 (SIGSEGV)
==16257== General Protection Fault
==16257== at 0x4E8F824: printf (printf.c:28)
==16257== by 0x40055F: printf_float (in /home/starsep/stack/main)
==16257== by 0x400534: ??? (printf.asm:6)
==16257== by 0x4E5A82F: (below main) (libc-start.c:291)
==16257==
==16257== HEAP SUMMARY:
==16257== in use at exit: 0 bytes in 0 blocks
==16257== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==16257==
==16257== All heap blocks were freed -- no leaks are possible
==16257==
==16257== For counts of detected and suppressed errors, rerun with: -v
==16257== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[1] 16257 segmentation fault valgrind ./main
Related
This is the first time I work with wchar and I found something surprising about it. I can't find the answer so I will share my experiences.
I have a simple test program (based on a swprintf example)
#include <stdio.h>
#include <wchar.h>
int main()
{
wchar_t str_unicode[100] = {0};
swprintf(str_unicode, sizeof(str_unicode), L"%3d\n", 120);
fputws(str_unicode, stdout);
return 0;
}
Compiling it with or without optimization works fine:
gcc -O2 test.c -o test
Running it also works fine:
./test
120
But in my current project, I use -D_FORTIFY_SOURCE=2, and it makes this simple program crash:
gcc -O2 -D_FORTIFY_SOURCE=2 test.c -o test
./test
*** buffer overflow detected ***: terminated
[1] 28569 IOT instruction (core dumped) ./test
I have more details with valgrind, and it seems that __swprintf_chk fails.
valgrind ./test
==30068== Memcheck, a memory error detector
==30068== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30068== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==30068== Command: ./test
==30068==
*** buffer overflow detected ***: terminated
==30068==
==30068== Process terminating with default action of signal 6 (SIGABRT): dumping core
==30068== at 0x48A29E5: raise (in /usr/lib64/libc-2.32.so)
==30068== by 0x488B8A3: abort (in /usr/lib64/libc-2.32.so)
==30068== by 0x48E5006: __libc_message (in /usr/lib64/libc-2.32.so)
==30068== by 0x4975DF9: __fortify_fail (in /usr/lib64/libc-2.32.so)
==30068== by 0x4974695: __chk_fail (in /usr/lib64/libc-2.32.so)
==30068== by 0x49752C4: __swprintf_chk (in /usr/lib64/libc-2.32.so)
==30068== by 0x401086: main (in /home/pierre/workdir/test)
==30068==
==30068== HEAP SUMMARY:
==30068== in use at exit: 0 bytes in 0 blocks
==30068== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==30068==
==30068== All heap blocks were freed -- no leaks are possible
==30068==
==30068== For lists of detected and suppressed errors, rerun with: -s
==30068== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[1] 30068 IOT instruction (core dumped) valgrind ./test
I don't understand why this check fails, the buffer size is more than enough (100) for a single integer. Is it a bug in libc? Or did I do something wrong?
My GCC version is 10.3.1
gcc --version
gcc (GCC) 10.3.1 20210422 (Red Hat 10.3.1-1)
Your problem is the second parameter of the function call -
swprintf(str_unicode, sizeof(str_unicode), L"%3d\n", 120);
You passed in the size in bytes of the entire array - i.e. 400 bytes if sizeof(wchar_t) == 4.
But swprintf's second parameter is the number of cells in the wchar_t array - i.e. 100 cells in your example.
Change your function call to:
swprintf(str_unicode, sizeof(str_unicode) / sizeof(wchar_t), L"%3d\n", 120);
I'm using valgrind 3.13 on mips platform, however I write a test program and found valgrind didn't trace to file line number, for x86 it works fine. what could be the problem?
# valgrind --trace-children=yes --leak-check=yes --num-callers=20 /tmp/a.out
==2957== Memcheck, a memory error detector
==2957== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2957== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2957== Command: /tmp/a.out
==2957==
==2957== Invalid write of size 4
==2957== at 0x4000B90: ??? (in /lib/ld-uClibc.so.0)
==2957== by 0x4000B3C: ??? (in /lib/ld-uClibc.so.0)
==2957== Address 0x7e8bdcbc is on thread 1's stack
==2957== 4 bytes below stack pointer
==2957==
==2957== Conditional jump or move depends on uninitialised value(s)
==2957== at 0x48B4A44: ??? (in /lib/libc.so.0)
==2957== by 0x48ADBE4: ??? (in /lib/libc.so.0)
==2957==
buf=test buf
in func1:x[10]=10
/tmp/a.out: can't resolve symbol '__libc_freeres'
==2957==
==2957== HEAP SUMMARY:
==2957== in use at exit: 0 bytes in 0 blocks
==2957== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2957==
==2957== All heap blocks were freed -- no leaks are possible
==2957==
==2957== For counts of detected and suppressed errors, rerun with: -v
==2957== Use --track-origins=yes to see where uninitialised values come from
==2957== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Below is my test.c, compiled with mips toolchain with option "-g -O0"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
func1()
{
int *x=malloc(10*sizeof(int *));
x[10]=10;
printf("in func1:x[10]=%d\n", x[10]);
}
main()
{
char buf[2];
char buf2[10];
strcpy(buf,"test buf\n");
printf("buf=%s\n", buf);
func1();
}
I'm not able to figure out why Valgrind is printing Invalid read of size 8 when using wchar_t. I'm running a 64bit Ubuntu (3.5.0-25) system with valgrind-3.7.0 and gcc 4.7.2.
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// const wchar_t *text = L"This is a t"; // no Valgrind error
// const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error
const wchar_t *text = L"This is a test"; // Valgrind ERRROR
wchar_t *new_text = NULL;
new_text = (wchar_t*) malloc( (wcslen(text) + 1) * sizeof(wchar_t));
wcsncpy(new_text, text, wcslen(text));
new_text[wcslen(text)] = L'\0';
printf("new_text: %ls\n", new_text);
free(new_text);
return 0;
}
Compile:
$ gcc -g -std=c99 test.c -o test
$ valgrind --tool=memcheck --leak-check=full --track-origins=yes --show-reachable=yes ./test
Valgrind results:
==19495== Memcheck, a memory error detector
==19495== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==19495== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==19495== Command: ./test
==19495==
==19495== Invalid read of size 8
==19495== at 0x4ED45A7: wcslen (wcslen.S:55)
==19495== by 0x4ED5C0E: wcsrtombs (wcsrtombs.c:74)
==19495== by 0x4E7D160: vfprintf (vfprintf.c:1630)
==19495== by 0x4E858D8: printf (printf.c:35)
==19495== by 0x4006CC: main (test.c:16)
==19495== Address 0x51f1078 is 56 bytes inside a block of size 60 alloc'd
==19495== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19495== by 0x40066F: main (test.c:12)
==19495==
new_text: This is a test
==19495==
==19495== HEAP SUMMARY:
==19495== in use at exit: 0 bytes in 0 blocks
==19495== total heap usage: 1 allocs, 1 frees, 60 bytes allocated
==19495==
==19495== All heap blocks were freed -- no leaks are possible
==19495==
==19495== For counts of detected and suppressed errors, rerun with: -v
==19495== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
Now if I run the same but with a 'working string', let's say
const wchar_t *text = L"This is a t"; // no Valgrind error
// const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error
// const wchar_t *text = L"This is a test"; // Valgrind ERRROR
I get no issue:
==19571== Memcheck, a memory error detector
==19571== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==19571== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==19571== Command: ./test
==19571==
new_text: This is a t
==19571==
==19571== HEAP SUMMARY:
==19571== in use at exit: 0 bytes in 0 blocks
==19571== total heap usage: 1 allocs, 1 frees, 48 bytes allocated
==19571==
==19571== All heap blocks were freed -- no leaks are possible
==19571==
==19571== For counts of detected and suppressed errors, rerun with: -v
==19571== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
At first I thought the string size should be always be multiple of 8 (maybe some wcs read chunks of 8) but some cases failed, then I thought I'd have to append always 8 bytes for the NULL terminator ((wcslen(item) + 2) * sizeof(wchar_t)), it worked but that doesn't make any sense since sizeof(wchar_t) - in my system - is 4 bytes and should be enough to handle the L'\0' terminator.
I also read the glibc wcslen source code but nothing new. I'm now thinking of Valgrind issue. Do you guys could throw some light here? Does it worth to file a bug against Valgrind?
Thank you
This is probably caused by SSE optimisation of the wcslen function; see e.g. https://bugzilla.redhat.com/show_bug.cgi?id=798968 or https://bugs.archlinux.org/task/30643.
When optimising wcslen, it's faster to read multiple wide characters at a time and use vectorised instructions (SSE) to compare them to L'\0'. Unfortunately valgrind sees this as an uninitialised read - which it is, but it's harmless because the result of wcslen does not depend on the uninitialised value.
The fix is to update valgrind in the hope that a newer version will suppress the false positive.
The code is here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buf = malloc(3);
strcpy(buf, "hi");
printf("%s\n", buf);
free(buf);
}
It's compiled with:
gcc a.c && valgrind ./a.out
The error message is here:
==1421== Memcheck, a memory error detector
==1421== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==1421== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==1421== Command: ./a.out
==1421==
==1421== Invalid read of size 8
==1421== at 0x4EA96C1: ??? (in /lib/libc-2.14.1.so)
==1421== by 0x4E92D3B: puts (in /lib/libc-2.14.1.so)
==1421== by 0x4005BB: main (in /home/peter/a.out)
==1421== Address 0x51b4040 is 0 bytes inside a block of size 3 alloc'd
==1421== at 0x4C2740D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1421== by 0x400595: main (in /home/peter/a.out)
==1421==
hi
==1421==
==1421== HEAP SUMMARY:
==1421== in use at exit: 0 bytes in 0 blocks
==1421== total heap usage: 1 allocs, 1 frees, 3 bytes allocated
==1421==
==1421== All heap blocks were freed -- no leaks are possible
==1421==
==1421== For counts of detected and suppressed errors, rerun with: -v
==1421== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 6 from 6)
It is also very strange that valgrind reports no more errors if I use the following (just one more space):
printf("%s \n", buf);
Would anyone please help me?
This is a bug, but not reproducible on all machines.
On some machines, gcc optimizes simple printf() with, for example, puts(), which could possibly involve invalid read (or just valgrind thinks so).
If it really matters, you can 'complicate' the printf format. A space between %s and \n would do.
Here is a similar bug: C strings, strlen and Valgrind
This answer combines comments in the discussion. Thank you all!
I've run it in my own machine, and I get no errors:
==61755== Memcheck, a memory error detector
==61755== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==61755== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==61755== Command: ./a.out
==61755==
hi
==61755==
==61755== HEAP SUMMARY:
==61755== in use at exit: 0 bytes in 0 blocks
==61755== total heap usage: 1 allocs, 1 frees, 3 bytes allocated
==61755==
==61755== All heap blocks were freed -- no leaks are possible
==61755==
==61755== For counts of detected and suppressed errors, rerun with: -v
==61755== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
The code is here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buf = malloc(3);
strcpy(buf, "hi");
printf("%s\n", buf);
free(buf);
}
It's compiled with:
gcc a.c && valgrind ./a.out
The error message is here:
==1421== Memcheck, a memory error detector
==1421== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==1421== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==1421== Command: ./a.out
==1421==
==1421== Invalid read of size 8
==1421== at 0x4EA96C1: ??? (in /lib/libc-2.14.1.so)
==1421== by 0x4E92D3B: puts (in /lib/libc-2.14.1.so)
==1421== by 0x4005BB: main (in /home/peter/a.out)
==1421== Address 0x51b4040 is 0 bytes inside a block of size 3 alloc'd
==1421== at 0x4C2740D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1421== by 0x400595: main (in /home/peter/a.out)
==1421==
hi
==1421==
==1421== HEAP SUMMARY:
==1421== in use at exit: 0 bytes in 0 blocks
==1421== total heap usage: 1 allocs, 1 frees, 3 bytes allocated
==1421==
==1421== All heap blocks were freed -- no leaks are possible
==1421==
==1421== For counts of detected and suppressed errors, rerun with: -v
==1421== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 6 from 6)
It is also very strange that valgrind reports no more errors if I use the following (just one more space):
printf("%s \n", buf);
Would anyone please help me?
This is a bug, but not reproducible on all machines.
On some machines, gcc optimizes simple printf() with, for example, puts(), which could possibly involve invalid read (or just valgrind thinks so).
If it really matters, you can 'complicate' the printf format. A space between %s and \n would do.
Here is a similar bug: C strings, strlen and Valgrind
This answer combines comments in the discussion. Thank you all!
I've run it in my own machine, and I get no errors:
==61755== Memcheck, a memory error detector
==61755== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==61755== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==61755== Command: ./a.out
==61755==
hi
==61755==
==61755== HEAP SUMMARY:
==61755== in use at exit: 0 bytes in 0 blocks
==61755== total heap usage: 1 allocs, 1 frees, 3 bytes allocated
==61755==
==61755== All heap blocks were freed -- no leaks are possible
==61755==
==61755== For counts of detected and suppressed errors, rerun with: -v
==61755== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)