Is there an 'Integral constant overflow' warning in clang? - c

Consider the following snippets:
short x = 2000000000;
short x = (short)2000000000;
int x = 1000000000 * 1000000000;
Can we get an warning(/error) for these in Clang? How? Starting with what version?
Thanks,
Ciprian.

As of clang 3.3, at least, you get warnings in both cases without even trying:
/* main.c */
short x = 2000000000;
int y = 1000000000 * 1000000000;
int main()
{
return 0;
}
Compile:
$ clang -c main.c
main.c:1:11: warning: implicit conversion from 'int' to 'short' changes value
from 2000000000 to -27648 [-Wconstant-conversion]
short x = 2000000000;
~ ^~~~~~~~~~
main.c:2:20: warning: overflow in expression; result is -1486618624 with type
'int' [-Winteger-overflow]
int y = 1000000000 * 1000000000;
^
2 warnings generated.

Related

I have header file in /usr/include/bpf directory called tracing.h And including it seems to causing problem. I couldn't use it in include w/w-out -I

I have this header and function defined in it called long ptr = PT_REGS_PARM2(ctx); so first running command like following assuming my system config will take care of it finding this header file in /usr/include/bpf/tracing.h.
but couldn't find the header file
root#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g -target bpf -I /usr/include/ -c kprobe_send.c -o kprobe_send.o
I also tried with - I and changing <bpf/tracing.h> to "bpf/tracing.h" not worked either.
I started this inclusion of -I after I was compiling this program and it causing error on compile, I could not understand the error but this is following
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g-target bpf -c kprobe_send.c -o kprobe_send.o
clang: error: unknown argument: '-g-target'
clang: error: no such file or directory: 'bpf'
root#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g -target bpf -c kprobe_send.c -o kprobe_send.o
kprobe_send.c:31:2: warning: implicit declaration of function 'srand' is invalid in C99 [-Wimplicit-function-declaration]
srand(time(NULL)); /* Seed the random number generator. */
^
kprobe_send.c:37:11: warning: implicit declaration of function 'rand' is invalid in C99 [-Wimplicit-function-declaration]
int c = randrange(MAX-i);
^
kprobe_send.c:11:22: note: expanded from macro 'randrange'
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
^
kprobe_send.c:51:22: warning: implicit declaration of function 'PT_REGS_PARM2' is invalid in C99 [-Wimplicit-function-declaration]
char *ptr = PT_REGS_PARM2(ctx);
^
kprobe_send.c:51:15: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion]
char *ptr = PT_REGS_PARM2(ctx);
^ ~~~~~~~~~~~~~~~~~~
kprobe_send.c:61:22: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'void *' [-Wint-conversion]
bpf_map_update_elem(fd,&key,&data,BPF_ANY);
^~
Error at line 37: Unsupport signed division for DAG: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11Please convert to unsigned div/mod.
fatal error: error in backend: Cannot select: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11
0x18af668: i64 = sra 0x189bcd8, Constant:i64<32>, kprobe_send.c:37:11
0x189bcd8: i64 = shl 0x189c4f8, Constant:i64<32>, kprobe_send.c:37:11
0x189c4f8: i64,ch,glue = CopyFromReg 0x189c018, Register:i64 $r0, 0x189c018:1, kprobe_send.c:37:11
0x189c150: i64 = Register $r0
0x189c018: ch,glue = callseq_end 0x189bc08, TargetConstant:i64<0>, TargetConstant:i64<0>, 0x189bc08:1, kprobe_send.c:37:11
0x189bfb0: i64 = TargetConstant<0>
0x189bfb0: i64 = TargetConstant<0>
What the above error even means, I thought it was complaining I did not include any headers so I started including tracing.h to cater to PT_REGS_PARM2(ctx)
How can I get rid of this error?
On this line it says unsupported sign division:
Error at line 37: Unsupport signed division for DAG: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11Please convert to unsigned div/mod.
Is this line 37 referring to assembly or my source file? In line 37 of source file I am doing
int c = randrange(MAX-i);
Why is the above simple line is not allowed in ebpf program? This is my line 37 and rest of the bpf program
#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
//#include <bpf/tracing.h>
#include <stdlib.h>
#define RAND_MAX 0x7fff
#define PERF_SAMPLE_RAW 1U << 0
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
#define MAX 100000000 /* Values will be in the range (1 .. MAX) */
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
__uint(max_entries, 100);
} my_map SEC(".maps");
SEC("kprobe/__x64_sys_recvfrom")
int bpf_prog1(struct pt_regs *ctx,int fd, const char *buf, size_t count)
{
static int vektor[100000000];
int candidates[MAX];
int i;
long key;
srand(time(NULL)); /* Seed the random number generator. */
for (i=0; i<MAX; i++)
candidates[i] = i;
for (i = 0; i < MAX-1; i++) {
int c = randrange(MAX-i);
int t = candidates[i];
candidates[i] = candidates[i+c];
candidates[i+c] = t;
}
for (i=0; i<10; i++)
vektor[i] = candidates[i] + 1;
struct S {
int pid;
char cookie[90];
char *ptr;
} data={1,""};
char *ptr = PT_REGS_PARM2(ctx);
//data.pid =count;// bpf_get_current_pid_tgid();
//if(buf==NULL)
//memcpy(data.cookie,buf,20);
data.ptr=ptr;
// data.cookie[0]=buf[0];
//bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
key=vektor[i];
bpf_map_update_elem(fd,&key,&data,BPF_ANY);
//bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
return 0;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = 99;
is there any info source where it says what's allowed or what's not allowed because seems to me its just picking arbitrarily what's allowed and what's not looking into ebpf
My kernel: 5.14.1
My clang: 12
libbpf installed but I'd love to find a command that tells its version and or just where it's installed.
On some link I found it says maybe/or definitely (couldn't tell the difference) be a problem of symlink on Ubuntu exact source .. what this even means does it mean I installed libbpf or something and unbuntu messed up with my symlink that help find libbpf headers? How can I understand what this link says? https://github.com/iovisor/kubectl-trace/issues/76#issuecomment-513587108

Is this clang optimization a bug?

I ran into an interesting issue when compiling some code with -O3 using clang on OSX High Sierra. The code is this:
#include <stdint.h>
#include <limits.h> /* for CHAR_BIT */
#include <stdio.h> /* for printf() */
#include <stddef.h> /* for size_t */
uint64_t get_morton_code(uint16_t x, uint16_t y, uint16_t z)
{
/* Returns the number formed by interleaving the bits in x, y, and z, also
* known as the morton code.
*
* See https://graphics.stanford.edu/~seander/bithacks.html#InterleaveTableO
bvious.
*/
size_t i;
uint64_t a = 0;
for (i = 0; i < sizeof(x)*CHAR_BIT; i++) {
a |= (x & 1U << i) << (2*i) | (y & 1U << i) << (2*i + 1) | (z & 1U << i)
<< (2*i + 2);
}
return a;
}
int main(int argc, char **argv)
{
printf("get_morton_code(99,159,46) = %llu\n", get_morton_code(99,159,46));
return 0;
}
When compiling this with cc -O1 -o test_morton_code test_morton_code.c I get the following output:
get_morton_code(99,159,46) = 4631995
which is correct. However, when compiling with cc -O3 -o test_morton_code test_morton_code.c:
get_morton_code(99,159,46) = 4294967295
which is wrong.
What is also odd is that this bug appears in my code when switching from -O2 to -O3 whereas in the minimal working example above it appears when going from -O1 to -O2.
Is this a bug in the compiler optimization or am I doing something stupid that's only appearing when the compiler is optimizing more aggressively?
I'm using the following version of clang:
snotdaqs-iMac:snoFitter snoperator$ cc --version
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
UndefinedBehaviorSanitizer is really helpful in catching such mistakes:
$ clang -fsanitize=undefined -O3 o3.c
$ ./a.out
o3.c:19:2: runtime error: shift exponent 32 is too large for 32-bit type 'unsigned int'
get_morton_code(99,159,46) = 4294967295
A possible fix would be replacing the 1Us with 1ULL, an unsigned long long is at least 64 bit and can be shifted that far.
When i is 15 in the loop, 2*i+2 is 32, and you are shifting an unsigned int by the number of bits in an unsigned int, which is undefined.
You apparently intend to work in a 64-bit field, so cast the left side of the shift to uint64_t.
A proper printf format for uint64_t is get_morton_code(99,159,46) = %" PRIu64 "\n". PRIu64 is defined in the <inttypes.h> header.

C11 _Generic c program and errors on Eclipse c/c++

Hi i was studying C for the first time using C primer plus book then in chapter 16 about _Generic from C11 standard i wrote a program in Eclipse c/c++ and build and it produces 8 errors and warning and i don't know why here is the program and the errors
#include <stdio.h>
#include <math.h>
#define RAD_TO_DEG (180/(4 * atanl(1)))
// generic square root function
#define SQRT(X) _Generic((X),\
long double: sqrtl, \
default: sqrt, \
float: sqrtf)(X)
// generic sine function, angle in degrees
#define SIN(X) _Generic((X),\
long double: sinl((X)/RAD_TO_DEG),\
default: sin((X)/RAD_TO_DEG),\
float: sinf((X)/RAD_TO_DEG)\
)
int main(void)
{
float x = 45.0f;
double xx = 45.0;
long double xxx =45.0L;
long double y = SQRT(x);
long double yy= SQRT(xx);
long double yyy = SQRT(xxx);
printf("%.17Lf\n", y); // matches float
printf("%.17Lf\n", yy); // matches default
printf("%.17Lf\n", yyy); // matches long double
int i = 45;
yy = SQRT(i); // matches default
printf("%.17Lf\n", yy);
yyy= SIN(xxx); // matches long double
printf("%.17Lf\n", yyy);
return 0;
}
errors
make all
Building file: ../generic.c
Invoking: GCC C Compiler
gcc -std=c11 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"generic.d" -MT"generic.d" -o "generic.o" "../generic.c"
../generic.c: In function ‘main’:
../generic.c:24:5: warning: implicit declaration of function ‘_Generic’ [-Wimplicit-function-declaration]
long double y = SQRT(x);
^
../generic.c:7:5: error: expected expression before ‘long’
long double: sqrtl, \
^
../generic.c:24:21: note: in expansion of macro ‘SQRT’
long double y = SQRT(x);
^
../generic.c:7:5: error: expected expression before ‘long’
long double: sqrtl, \
^
../generic.c:25:21: note: in expansion of macro ‘SQRT’
long double yy= SQRT(xx);
^
../generic.c:7:5: error: expected expression before ‘long’
long double: sqrtl, \
^
../generic.c:26:23: note: in expansion of macro ‘SQRT’
long double yyy = SQRT(xxx);
^
../generic.c:7:5: error: expected expression before ‘long’
long double: sqrtl, \
^
../generic.c:31:10: note: in expansion of macro ‘SQRT’
yy = SQRT(i); // matches default
^
../generic.c:13:1: error: expected expression before ‘long’
long double: sinl((X)/RAD_TO_DEG),\
^
../generic.c:33:10: note: in expansion of macro ‘SIN’
yyy= SIN(xxx); // matches long double
^
make: *** [generic.o] Error 1
14:47:53 Build Finished (took 66ms)
i have used -lm link for math.h and it produces these errors and i don't know why ?
Reason:
_Generic is not supported in gcc until version 4.9, see: https://gcc.gnu.org/wiki/C11Status
Solution:
Try a newer version of gcc.
Example:
In a.c is the code you provided:
[pengyu#GLaDOS tmp]$ gcc a.c -std=c11 -lm -Wall -pedantic
[pengyu#GLaDOS tmp]$ gcc --version | head -n 1
gcc (GCC) 4.9.1 20140903 (prerelease)

gcc -O3 , data pointer seems to get lost

Depending on optimization level the output differ as follows:
With unexpected output:
$ gcc -Wall -O3 otest.c -o otest
$ otest
*x: 0
y: 2048.899902
y: 0.000000
With expected output:
$ gcc -Wall -O2 otest.c -o otest
$ otest
*x: 45000e66
y: 0.000000
y: 2048.899902
source code :
#include <stdio.h>
int main(void)
{
float y = 2048.9;
void *p = &y;
unsigned int *x = p;
printf(" *x: %x \n",*x);
*x = 0;
printf(" y: %f \n",y);
*x = 0x45000e66;
printf(" y: %f \n",y);
return 0;
}
gcc version is 4.2.1.
Am I missing any important directive ?
Yes. Your code is violating the strict aliasing rule (when you have a float, but you access it through a pointer to unsigned int, which is an incompatible type), invoking undefined behavior, so the compiler is allowed to do anything it pleases with your code, including entirely eliminating parts of it.

Why does this code cause a Floating point exception - SIGFPE

Using gcc 4.7:
$ gcc --version
gcc (GCC) 4.7.0 20120505 (prerelease)
Code listing (test.c):
#include <stdint.h>
struct test {
int before;
char start[0];
unsigned int v1;
unsigned int v2;
unsigned int v3;
char end[0];
int after;
};
int main(int argc, char **argv)
{
int x, y;
x = ((uintptr_t)(&((struct test*)0)->end)) - ((uintptr_t)(&((struct test*)0)->start));
y = ((&((struct test*)0)->end)) - ((&((struct test*)0)->start));
return x + y;
}
Compile & execute
$ gcc -Wall -o test test.c && ./test
Floating point exception
The SIGFPE is caused by the second assignment (y = ...). In the assembly listing, there is a division on this line? Note that the only difference between x= and y= is casting to (uintptr_t).
Disregarding the undefined behaviour due to violation of constarints in the standard, what gcc does here is to calculate the difference between two pointers to char[0] - &(((struct test*)0)->start) and &(((struct test*)0)->end), and divide that difference by the size of a char[0], which of course is 0, so you get a division by 0.

Resources