473,387 Members | 1,579 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Strange syntax

Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);
}
What is the meaning of "(void*)(long)(priv != 0)" ?

TIA

Regards,
Seenu.

Note: Even though this code is not existing in the current kernel, it
was avlbl in 2.4.xx.
Dec 5 '07 #1
18 1859
se*****@gmail.com said:
Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);
}
What is the meaning of "(void*)(long)(priv != 0)" ?
It means "warning! dodgy code! fix me!"

(priv != 0) yields a result that is either 0 or 1.
Casting this to (long) yields a value that is either 0L or 1L.
Casting to to (void *) yields a value that is very unlikely to be a valid
pointer to any object or function.

Stupid stupid stupid.
Note: Even though this code is not existing in the current kernel, it
was avlbl in 2.4.xx.
So what you're saying, then, is that someone came to their senses and
ripped it out. Good!

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Dec 5 '07 #2
On Dec 5, 12:33 am, seen...@gmail.com wrote:
Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);

}

What is the meaning of "(void*)(long)(priv != 0)" ?

TIA
The second parameter has the type struct siginfo*. A NULL (0) pointer
here means a user kill sig. The special reserved pointer (struct
siginfo*)1 is for kernel sigs. (priv != 0) has value 0 if priv is 0
and 1 otherwise. The casts coerce this int value to a compatible
pointer. The effect is that privilege level 0 causes a user sig and
all others a kernel sig. It's not clear to me why (void*)(long) is
used instead of (struct siginfo*), but the effect ought to be the
same.

Dec 5 '07 #3
Richard Heathfield wrote:
se*****@gmail.com said:
>Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);
}
What is the meaning of "(void*)(long)(priv != 0)" ?

It means "warning! dodgy code! fix me!"

(priv != 0) yields a result that is either 0 or 1.
Casting this to (long) yields a value that is either 0L or 1L.
Casting to to (void *) yields a value that is very unlikely to be a valid
pointer to any object or function.

Stupid stupid stupid.
To be fair, code found in linux/kernel/anything is unlikely to be written
in portable standard C and may be permitted to exploit implementation-
specific details. (The casting looks bizarre, but for all we know, it
could be avoiding an implementation-specific bug.)

As you know, Bob, the standard doesn't stop you from relying on
implementation details; it just doesn't define what happens if you
do. Sometimes this is a Good Thing.

--
Chris "it only /looks/ like C" Dollin

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Dec 5 '07 #4
Chris Dollin said:

<snip>
To be fair, code found in linux/kernel/anything is unlikely to be written
in portable standard C and may be permitted to exploit implementation-
specific details.
Understood - but disguising a flag as a pointer is Just Plain Daft. I've
seen the same trick used a few times in application code. It was daft
then, and it's daft now. Obfuscation, sheer obfuscation.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Dec 5 '07 #5
Richard Heathfield wrote:
Chris Dollin said:

<snip>
>To be fair, code found in linux/kernel/anything is unlikely to be written
in portable standard C and may be permitted to exploit implementation-
specific details.

Understood - but disguising a flag as a pointer is Just Plain Daft.
Hmmm... It's just a special value, and I'm not convinced it's
significantly different to the special value returned by getc() to
indicate end of file, or (more to the point) the SIG_* macros in
<signal.h>.

Dec 5 '07 #6
In article <Ce******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>Chris Dollin said:

<snip>
>To be fair, code found in linux/kernel/anything is unlikely to be written
in portable standard C and may be permitted to exploit implementation-
specific details.

Understood - but disguising a flag as a pointer is Just Plain Daft. I've
seen the same trick used a few times in application code. It was daft
then, and it's daft now. Obfuscation, sheer obfuscation.
Which means that you should be right at home with it.

Dec 5 '07 #7
In article <Ce******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>Understood - but disguising a flag as a pointer is Just Plain Daft. I've
seen the same trick used a few times in application code. It was daft
then, and it's daft now. Obfuscation, sheer obfuscation.
It might be wise to use a #define for it, but if we allow NULL pointers,
why not several varieties of not-a-pointer value?

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Dec 5 '07 #8
Richard Tobin said:
In article <Ce******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>>Understood - but disguising a flag as a pointer is Just Plain Daft. I've
seen the same trick used a few times in application code. It was daft
then, and it's daft now. Obfuscation, sheer obfuscation.

It might be wise to use a #define for it, but if we allow NULL pointers,
why not several varieties of not-a-pointer value?
Why not a method that is guaranteed by ISO to work?

For example, have a couple of file scope objects, defined in Some
Appropriate Place and declared in a header:

void * const G_flag_off = &G_flag_off;
void * const G_flag_on = &G_flag_on;

Then you can do, say, something like this:

return send_sig_info(sig, priv != 0 ? G_flag_on : G_flag_off, p);

Of course, you could wrap it up a bit prettier than that, and equally
of-coursely, the callee would need to know about the changed convention.
But this is hardly difficult, surely?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Dec 5 '07 #9
In article <WL*********************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>Why not a method that is guaranteed by ISO to work?

For example, have a couple of file scope objects, defined in Some
Appropriate Place and declared in a header:

void * const G_flag_off = &G_flag_off;
void * const G_flag_on = &G_flag_on;
This has two minor disadvantages: it requires space for the objects,
which might be large, and the values are not constants.

And in the case cited - an operating system kernel - the code has no
need to be guaranteed-by-ISO-to-work.

There are also cases where your solution won't work because the
interface is across an operating system boundary. For example
the unix function mmap() returns (void *)-1 on error, and it
couldn't use the address of an object instead unless the kernel
and user programs shared some address space.

But in typical cases, your solution is preferable.

-- Richard
--
:wq
Dec 5 '07 #10
Chris Dollin <ch**********@hp.comwrites:
Richard Heathfield wrote:
>se*****@gmail.com said:
>>Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);
}
What is the meaning of "(void*)(long)(priv != 0)" ?

It means "warning! dodgy code! fix me!"

(priv != 0) yields a result that is either 0 or 1.
Casting this to (long) yields a value that is either 0L or 1L.
Casting to to (void *) yields a value that is very unlikely to be a valid
pointer to any object or function.

Stupid stupid stupid.

To be fair, code found in linux/kernel/anything is unlikely to be written
in portable standard C and may be permitted to exploit implementation-
specific details. (The casting looks bizarre, but for all we know, it
could be avoiding an implementation-specific bug.)

As you know, Bob, the standard doesn't stop you from relying on
implementation details; it just doesn't define what happens if you
do. Sometimes this is a Good Thing.
Is there anything wrong with comparing that void * with (void *)(1L) in
the calling hierarchy elsewhere?

Its almost certainly an optimization to pass back control flags or
pointers depending on usage.
Dec 5 '07 #11
Richard wrote:
Chris Dollin <ch**********@hp.comwrites:
>Richard Heathfield wrote:
>>se*****@gmail.com said:

Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);
}
What is the meaning of "(void*)(long)(priv != 0)" ?

It means "warning! dodgy code! fix me!"

(priv != 0) yields a result that is either 0 or 1.
Casting this to (long) yields a value that is either 0L or 1L.
Casting to to (void *) yields a value that is very unlikely to be a
valid pointer to any object or function.

Stupid stupid stupid.

To be fair, code found in linux/kernel/anything is unlikely to be
written in portable standard C and may be permitted to exploit
implementation- specific details. (The casting looks bizarre, but for
all we know, it could be avoiding an implementation-specific bug.)

As you know, Bob, the standard doesn't stop you from relying on
implementation details; it just doesn't define what happens if you
do. Sometimes this is a Good Thing.

Is there anything wrong with comparing that void * with (void *)(1L)
in the calling hierarchy elsewhere?

Its almost certainly an optimization to pass back control flags or
pointers depending on usage.
In x86 under flat memory model a general purpose register can contain a
pointer and they are compatible with ordinary integer values, which is
the reason why the Linux kernel source can do these sort of tricks.
Presumably code such as these would be rewritten for another
incompatible architecture, for a port.

Dec 5 '07 #12
Richard Tobin said:
In article <WL*********************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>>Why not a method that is guaranteed by ISO to work?

For example, have a couple of file scope objects, defined in Some
Appropriate Place and declared in a header:

void * const G_flag_off = &G_flag_off;
void * const G_flag_on = &G_flag_on;

This has two minor disadvantages: it requires space for the objects,
which might be large, and the values are not constants.
Yes, I agree, although it is at least *unlikely* that they will be large.
Typically they'll be 16, 32 or possibly even 64 bits each, but probably
not larger than that (for now, anyway). As for the values not being
constants, well, that's also true, but the constness should at least warn
people off, if nothing else.
And in the case cited - an operating system kernel - the code has no
need to be guaranteed-by-ISO-to-work.
Again, true - but I'm very much in the "make it portable unless you have a
darn good reason not to" camp, and this case doesn't strike me as having a
darn good reason not to.
There are also cases where your solution won't work because the
interface is across an operating system boundary. For example
the unix function mmap() returns (void *)-1 on error, and it
couldn't use the address of an object instead unless the kernel
and user programs shared some address space.
Okay, and I realise that nobody is about to rewrite the entire kernel to my
spec, but whoever designed mmap needs a good kicking. It should return
NULL on error.
But in typical cases, your solution is preferable.
Aye.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Dec 5 '07 #13
In article <Js******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>Okay, and I realise that nobody is about to rewrite the entire kernel to my
spec, but whoever designed mmap needs a good kicking. It should return
NULL on error.
I assume it's possible (or was considered to be, when the interface
was specified) for it to return a region mapped at address zero, which
has the same representation as a NULL pointer on the systems in
question.

-- Richard
--
:wq
Dec 5 '07 #14
Chris Torek wrote:

<snip history of mmap()' interface in relation to the evolution of UNIX>

That was a very interesting post. Thanks.

Dec 5 '07 #15
In article <Js******************************@bt.comrj*@see.sig.invalid writes:
Richard Tobin said:
....
There are also cases where your solution won't work because the
interface is across an operating system boundary. For example
the unix function mmap() returns (void *)-1 on error, and it
couldn't use the address of an object instead unless the kernel
and user programs shared some address space.

Okay, and I realise that nobody is about to rewrite the entire kernel to my
spec, but whoever designed mmap needs a good kicking. It should return
NULL on error.
But also NULL is not necessarily the same across OS boundaries. I have used
at least one system where a kernel NULL was different from a user NULL (the
pointer contains ring information that is inherently not equal for kernel
and user space).
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Dec 6 '07 #16
In article <fj**********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
>I assume it's possible (or was considered to be, when the interface
was specified) for it to return a region mapped at address zero, which
has the same representation as a NULL pointer on the systems in
question.
Though Chris has explained that it's just a historical consequence of
the way unix system calls returned errors, it is in fact possible on
the system I'm using to mmap() a file at address zero, and have mmap()
succeed and return a [pointer identical to the] null pointer.

The program below, running on an Apple Powerbook under MacOS X 10.4
with /etc/motd as standard input, prints

mmap()ed at 0x0
Welcome to Darwin!

Given a much larger file, it gets an illegal instruction, presumably because
it has mapped the file over the executable code.

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>

int main(void)
{
int i;
void *memory;
struct stat sb;

if(fstat(0, &sb) == -1)
{
perror("fstat");
return 1;
}

if((memory = mmap(0, sb.st_size, PROT_READ, MAP_FIXED|MAP_PRIVATE, 0, 0)) == (void *)-1)
{
perror("mmap");
return 0;
}

printf("mmap()ed at %p\n", memory);

for(i=0; i<sb.st_size; i++)
putchar(*(char *)i);

return 0;
}

-- Richard
--
:wq
Dec 6 '07 #17
Chris Torek wrote:
Indeed -- although in this case, the "broken" interface is now
enshrined in a standard (not Standard C, but POSIX). It might help
to illustrate a bit how the situation came about, and how it could
have been avoided, though.
Thanks for, and for taking the trouble to write, that historical view.

--
Chris "no, not that one" Dollin

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

Dec 6 '07 #18
Richard Heathfield wrote:
se*****@gmail.com said:
>Hi All,
I found a piece of code in linux/kernel/signal.c:

int
send_sig(int sig, struct task_struct *p, int priv)
{
return send_sig_info(sig, (void*)(long)(priv != 0), p);
}
What is the meaning of "(void*)(long)(priv != 0)" ?

It means "warning! dodgy code! fix me!"

(priv != 0) yields a result that is either 0 or 1.
Casting this to (long) yields a value that is either 0L or 1L.
Casting to to (void *) yields a value that is very unlikely to be a valid
pointer to any object or function.
In <sched.h>, one can now find

#define SEND_SIG_NOINFO ((struct siginfo *) 0)
#define SEND_SIG_PRIV ((struct siginfo *) 1)

which I guess give a clue to what the programmer intended.
Stupid stupid stupid.
Agreed, very obfuscated code.

>Note: Even though this code is not existing in the current kernel, it
was avlbl in 2.4.xx.

So what you're saying, then, is that someone came to their senses and
ripped it out. Good!
Yes, the current send_sig() function, doesn't look anything like OP's
version.

--
Tor <bw****@wvtqvm.vw | tr i-za-h a-z>
Dec 9 '07 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: Allcomp | last post by:
Hello, I have seen something really strange in VB6 If I do a Int ( (5 * 1.2)) , I receive the value 5, but I should receive 6? Is this a bug or something really "normal". I can see that if I...
7
by: Aaron Prohaska | last post by:
I have just run into a problem where I have a page that posts back to itself to execute code, except when the page does the post back it somehow executes code that is in our home page for the site....
2
by: Olaf | last post by:
I have a frameset page witch contains the myFuc() function. The function is accessed from a page in one of the frames in the frameset. An example is shown below. <input...
8
by: Harvey Twyman | last post by:
I have code written under the CCS 'C' Compiler to run on a PIC microcontroller. Code Extract: ------------------------------- char a,b,c; ------------------------------- c = ( a == b );...
11
by: Dagwood Bumstead | last post by:
I play around with js a little... I just don't get this. The file below is just trying out some things... it does exactly what I want (hides/displays some things, no big deal) The problem is...
10
by: hg | last post by:
Hi, I'v been facing some very strange errors lately: one example: def __init__(self): ..... import my_info some_text = my_info.T_SOME_TEXT
1
by: Dariusz Tomon | last post by:
Hello, Till yesterday everything went well but I had to install service pack 2 to windows 2003 serv. After that every time I get strange JS errors (but could not debug it). Example:...
9
by: Dave | last post by:
Hi guys, I have just set up a duplicate server running: apache 2.54, mysql 5.04 and php 5.04 This is the same setup as as the server we are using now, apart from the hardware inside. I have...
7
by: email7373388 | last post by:
I'm working on a program which has a strange operator, :>. This is the syntax: ((unsigned short)( var1)):>((void __near *)( var2 )) Any clue?
8
by: =?GB2312?B?yum09MXt?= | last post by:
today I forgot to include some header,then I found the error message by the compiler is quite strange. so I want to know exactly the inner details of the compiler impletation,if possible. and I...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.