1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 | /*-*- Mode: C; c-basic-offset: 8 -*-*/
/***
This file is part of libkanberra.
Copyright 2008 Lennart Poettering
libkanberra is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 2.1 of the
License, or (at your option) any later version.
libkanberra is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with libkanberra. If not, see
<http://www.gnu.org/licenses/>.
***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#include "kanberra.h"
static void callback(ka_context *c, uint32_t id, int error, void *userdata) {
fprintf(stderr, "callback called for id %u, error '%s', userdata=%p\n", id, ka_strerror(error), userdata);
}
int main(int argc, char *argv[]) {
ka_context *c;
ka_proplist *p;
int ret;
setlocale(LC_ALL, "");
ret = ka_context_create(&c);
fprintf(stderr, "create: %s\n", ka_strerror(ret));
/* Initialize a few meta variables for the following play()
* calls. They stay valid until they are overwritten with
* ka_context_change_props() again. */
ret = ka_context_change_props(c,
KA_PROP_APPLICATION_NAME, "An example",
KA_PROP_APPLICATION_ID, "org.freedesktop.libkanberra.Test",
KA_PROP_WINDOW_X11_SCREEN, getenv("DISPLAY"),<--- Passing NULL after the last typed argument to a variadic function leads to undefined behaviour. [+]Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.
The C99 standard, in section 7.15.1.1, states that if the type used by va_arg() is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined.
The value of the NULL macro is an implementation-defined null pointer constant (7.17), which can be any integer constant expression with the value 0, or such an expression casted to (void*) (6.3.2.3). This includes values like 0, 0L, or even 0LL.
In practice on common architectures, this will cause real crashes if sizeof(int) != sizeof(void*), and NULL is defined to 0 or any other null pointer constant that promotes to int.
To reproduce you might be able to use this little code example on 64bit platforms. If the output includes "ERROR", the sentinel had only 4 out of 8 bytes initialized to zero and was not detected as the final argument to stop argument processing via va_arg(). Changing the 0 to (void*)0 or 0L will make the "ERROR" output go away.
#include <stdarg.h>
#include <stdio.h>
void f(char *s, ...) {
va_list ap;
va_start(ap,s);
for (;;) {
char *p = va_arg(ap,char*);
printf("%018p, %s\n", p, (long)p & 255 ? p : "");
if(!p) break;
}
va_end(ap);
}
void g() {
char *s2 = "x";
char *s3 = "ERROR";
// changing 0 to 0L for the 7th argument (which is intended to act as sentinel) makes the error go away on x86_64
f("first", s2, s2, s2, s2, s2, 0, s3, (char*)0);
}
void h() {
int i;
volatile unsigned char a[1000];
for (i = 0; i<sizeof(a); i++)
a[i] = -1;
}
int main() {
h();
g();
return 0;
}
NULL);
fprintf(stderr, "change_props: %s\n", ka_strerror(ret));
ret = ka_context_open(c);
fprintf(stderr, "open: %s\n", ka_strerror(ret));
/* Now trigger a sound event, the quick version */
ret = ka_context_play(c, 0,
KA_PROP_EVENT_ID, "desktop-login",
KA_PROP_MEDIA_FILENAME, "/usr/share/sounds/bar.wav",
KA_PROP_MEDIA_NAME, "User has logged off from session",
KA_PROP_MEDIA_LANGUAGE, "en_EN",
KA_PROP_KANBERRA_CACHE_CONTROL, "permanent",<--- Passing NULL after the last typed argument to a variadic function leads to undefined behaviour. [+]Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.
The C99 standard, in section 7.15.1.1, states that if the type used by va_arg() is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined.
The value of the NULL macro is an implementation-defined null pointer constant (7.17), which can be any integer constant expression with the value 0, or such an expression casted to (void*) (6.3.2.3). This includes values like 0, 0L, or even 0LL.
In practice on common architectures, this will cause real crashes if sizeof(int) != sizeof(void*), and NULL is defined to 0 or any other null pointer constant that promotes to int.
To reproduce you might be able to use this little code example on 64bit platforms. If the output includes "ERROR", the sentinel had only 4 out of 8 bytes initialized to zero and was not detected as the final argument to stop argument processing via va_arg(). Changing the 0 to (void*)0 or 0L will make the "ERROR" output go away.
#include <stdarg.h>
#include <stdio.h>
void f(char *s, ...) {
va_list ap;
va_start(ap,s);
for (;;) {
char *p = va_arg(ap,char*);
printf("%018p, %s\n", p, (long)p & 255 ? p : "");
if(!p) break;
}
va_end(ap);
}
void g() {
char *s2 = "x";
char *s3 = "ERROR";
// changing 0 to 0L for the 7th argument (which is intended to act as sentinel) makes the error go away on x86_64
f("first", s2, s2, s2, s2, s2, 0, s3, (char*)0);
}
void h() {
int i;
volatile unsigned char a[1000];
for (i = 0; i<sizeof(a); i++)
a[i] = -1;
}
int main() {
h();
g();
return 0;
}
NULL);
fprintf(stderr, "play: %s\n", ka_strerror(ret));
/* Now trigger a sound event, the complex version */
ka_proplist_create(&p);
ka_proplist_sets(p, KA_PROP_EVENT_ID, "desktop-logout");
ka_proplist_sets(p, KA_PROP_MEDIA_FILENAME, "/usr/share/sounds/uxknkurz.wav");
ka_proplist_sets(p, KA_PROP_MEDIA_NAME, "New email received");
ka_proplist_setf(p, "test.foo", "%u", 4711);
ret = ka_context_play_full(c, 1, p, callback, (void*) 0x4711);
ka_proplist_destroy(p);
fprintf(stderr, "play_full: %s\n", ka_strerror(ret));
/* Now trigger a sound event, by filename */
ret = ka_context_play(c, 2,
KA_PROP_MEDIA_FILENAME, "/usr/share/sounds/freedesktop/stereo/audio-channel-front-left.ogg",
KA_PROP_MEDIA_NAME, "Front Left",
KA_PROP_MEDIA_LANGUAGE, "en_EN",<--- Passing NULL after the last typed argument to a variadic function leads to undefined behaviour. [+]Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.
The C99 standard, in section 7.15.1.1, states that if the type used by va_arg() is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined.
The value of the NULL macro is an implementation-defined null pointer constant (7.17), which can be any integer constant expression with the value 0, or such an expression casted to (void*) (6.3.2.3). This includes values like 0, 0L, or even 0LL.
In practice on common architectures, this will cause real crashes if sizeof(int) != sizeof(void*), and NULL is defined to 0 or any other null pointer constant that promotes to int.
To reproduce you might be able to use this little code example on 64bit platforms. If the output includes "ERROR", the sentinel had only 4 out of 8 bytes initialized to zero and was not detected as the final argument to stop argument processing via va_arg(). Changing the 0 to (void*)0 or 0L will make the "ERROR" output go away.
#include <stdarg.h>
#include <stdio.h>
void f(char *s, ...) {
va_list ap;
va_start(ap,s);
for (;;) {
char *p = va_arg(ap,char*);
printf("%018p, %s\n", p, (long)p & 255 ? p : "");
if(!p) break;
}
va_end(ap);
}
void g() {
char *s2 = "x";
char *s3 = "ERROR";
// changing 0 to 0L for the 7th argument (which is intended to act as sentinel) makes the error go away on x86_64
f("first", s2, s2, s2, s2, s2, 0, s3, (char*)0);
}
void h() {
int i;
volatile unsigned char a[1000];
for (i = 0; i<sizeof(a); i++)
a[i] = -1;
}
int main() {
h();
g();
return 0;
}
NULL);
fprintf(stderr, "play (by filename): %s\n", ka_strerror(ret));
fprintf(stderr, "Sleep half a second ...\n");
usleep(500000);
/* Stop one sound */
/* ret = ka_context_cancel(c, 0); */
/* fprintf(stderr, "cancel: %s\n", ka_strerror(ret)); */
fprintf(stderr, "Sleep 2s ...\n");
sleep(2);
/* .. */
ret = ka_context_destroy(c);
fprintf(stderr, "destroy: %s\n", ka_strerror(ret));
return 0;
}
|