First of all, it is important to say that the code will be a mess, I know that and there is a reason behind the messy code, but I prefer not to specify why to avoid going off track.
This snippet of code decrypts a pointer:
//LLUNGO is long long
//PLLUNGO is long long pointer
//SCANVELOCE is __fastcall
LLUNGO SCANVELOCE DecryptPointer(PPTR_SECRET _pSecret, PLLUNGO _OldPointer)
{
_OldPointer = (PLLUNGO) PTR_ENCRYPTION_ALGORITHM(*_OldPointer, _pSecret->Segreto);
INTERO Reference = GetReferenceToPtr(_pSecret, _OldPointer);
if (PTR_BAD_REFERENCE(Reference))
QUICK_PRINT("Bad reference error.\n");
return PTR_ENCRYPTION_ALGORITHM((LLUNGO)_pSecret->Riferimenti[Reference], _pSecret->Segreto);
}
using the following macros:
#define PTR_ENCRYPTION_ALGORITHM(PTR, KEY) (~(PTR ^ KEY))
#define PTR_BAD_REFERENCE(PTR) ((-1) == (PTR))
Now the problem is when I use the macro stated below, for some reason even if I am using the right arguments it is still throwing me this error:
no instance of overloaded function "DecryptPointer" corresponds to the
arguments.
Consider that NBYTE is BYTE and REGISTRA is the register keyword.
NBYTE SCANVELOCE MFINIT(LLUNGO _FuncAddr, PMUTILATE_FUNCTION _Function)
{
if (!_FuncAddr || !_Function)
return FALSO;
SELF_PTR_DECRYPTION( _FuncAddr ); //error thrown here
SELF_PTR_DECRYPTION( _Function ); //and here too!
for (REGISTRA PNBYTE Current = (PNBYTE)_FuncAddr; ; Current--)
{
if (MF_PUSH_EBP == *Current)
{
_Function->Inizio = (LLUNGO)Current;
break;
}
}
And the SELF_PTR_DECRYPTION macro + everything else necessary for the DecryptPointer function to work:
(PTR_SECRET being a struct)
#define SELF_PTR_DECRYPTION(X) ((X) = (PTR_DECRYPTION(X)))
#define PTR_DECRYPTION(X) DecryptPointer(&PTR_SECRET_NAME, X)
#define PTR_SECRET_NAME g_PTR_SECRET
INIT(PTR_SECRET PTR_SECRET_NAME);
Again sorry for the stupidly messy code, I'm struggling too, just like everyone reading this probably will, but again there is a reason behind the mess.
The solution has been found in the comments by #yano:
you've taken me straight to macro hell. If I'm following correctly,
_FuncAddr in the SELF_PTR_DECRYPTION( _FuncAddr ); call ends up being the 2nd argument to DecryptPointer, which expects a PLLUNGO type.
However, _FuncAddr is a LLUNGO type. And if its complaining about "no
overloaded function" it sounds like you're using a C++ compiler, not
C.
Many thanks, and sorry for the absolute mess of code I presented here.
Related
I work with old C project and should make there several changes
It has lots of macros....
The function calls are defined there as
#define myFunc(arg) myBaseFunc(arg)
bool myBaseFunc is a function, actually there are several myBaseFunc
(its a kind of polymorphism)
I need to add some check of arguments correctness to myFunc
Actually the project has :
#define checkArg(arg) {\
// lot of code
}
I can`t change checkArg implementation
1) I thought to //
/*It is not correct if I do `if(myFunc(arg))`*/
#define myFunc(arg)\
checkArg(arg)\
myBaseFunc(arg)
2)I thought to
/*It is better...but compiler doesn`t like code block `{}` inside`if(myFunc(arg))`*/
#define myFunc(arg)(\
checkArg(arg),\
myBaseFunc(arg))
Is there a workaround for this case
A possible solution is to check the arg before it is passed to the base function. That works however only if there's only a single argument.
#define myFunc(arg) myBaseFunc(checkArg(arg))
Your checkArg function(s) must be changed so that they return the same value they got as parameter, e.g.
int checkArg(int value) {
... test stuff
return value;
}
I think It is possible like this, but you need to know argument type:
int main_check_function(void* data) { // <= this type need to be type of functions.
checkArg(data);
return (myBaseFunc(data));
}
#define myFunc(arg) (main_check_function(arg))
Although as I told, it is limited to knowing type. I just added a function to project to check your code by running checkArg() and then running myBaseFunc(). This approach is simple, but it has that big drawback.
First, please consider the following piece of code (static function called once from main()):
#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define MAX_BUF ((UI_8)64)
typedef uint8_t UI_8
typedef int32_t SI_32
typedef char CHAR_8
static SI_32 ImuGpioFdOpen(UI_8 gpio)
{
SI_32 fd_gpio_open = -1;
SI_32 byte_count = -1;
CHAR_8 aux_buf[MAX_BUF] = {'\0'};
byte_count = snprintf(aux_buf, sizeof(aux_buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
if((byte_count > 0) && (byte_count < sizeof(aux_buf))){
fd_gpio_open = open(aux_buf, O_RDONLY | O_NONBLOCK );
if(fd_gpio_open < 0){
syslog (LOG_ERR,"gpio/fd_open");
fd_gpio_open = ERROR;
}
}
return fd_gpio_open;
}/*ImuGpioFdOpen*/
On the call to open(), static analysis with Polyspace Code Prover raises and alert regarding MISRA's "Dir 4.1 Run-time failures shall be minimized". The alerts says that: "first argument (file path) may not be a valid string"
We don't seem to understand the directive very well, because all our efforts to solve the alerts like this (we have several similar ones) are not yielding results. I mean, we are clearly not building the string correctly, but since the program compiles and runs correctly, we are at a loss.
What kind of run-time check are we missing?
Thank you!
EDIT: I forgot to mention that passing a string literal seems to work for Polyspace, but it doesn't work if we try to pass string generated at runtime (like in the code). Could it be because open()'s prototype declares that the first argument is const char* and Polyspace is taking it too seriously?
The issue has been judged to be a false positive. The alerts shall be justified accordingly.
Thanks!
I have a question about the function spinlock_check() used in spin_lock_init() macro.
The code of spinlock_check is written below and it returns address of rlock
static __always_inline raw_spinlock_t *spinlock_check(spinlock_t *lock)
{
return &lock->rlock;
}
It is used in the macro spin_lock_init. The code of this macro:
#define spin_lock_init(_lock) \
do { \
spinlock_check(_lock); \
raw_spin_lock_init(&(_lock)->rlock); \
} while (0)
I saw a question about this topic in here.
But i did not quite understand and I want to express doubts in my way.
The spin_lock_init() is a macro but spinlock_check() isnt a macro. Its an inline function. So I think there is no way for some compilation magic to happen here but I expect some magic during execution of those instructions.
What effect does spinlock_check() has?
Because nothing is using the return value of spinlock_check() function.
Even though spinlock_check() return something the next step is going to get executed anyways.
Because I saw its usage in one of the file and I thought that its different from min(x, y) macro.
Here is the usage which I found
#ifdef CONFIG_NUMA
static void do_numa_crng_init(struct work_struct *work)
{
int i;
struct crng_state *crng;
struct crng_state **pool;
pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
for_each_online_node(i) {
crng = kmalloc_node(sizeof(struct crng_state),
GFP_KERNEL | __GFP_NOFAIL, i);
spin_lock_init(&crng->lock);
crng_initialize(crng);
pool[i] = crng;
}
mb();
if (cmpxchg(&crng_node_pool, NULL, pool)) {
for_each_node(i)
kfree(pool[i]);
kfree(pool);
}
}
So here crng is dynamically allocated one. say I have missed the kmalloc code meaning I haven't allocated memory for crng but still I used the macro spin_lock_init(crng).
Now what good the spinlock_check() function does ?
Isn't it that after spinlock_check() function raw_spin_lock_init automatically executes ?
If it is going to execute then whats the use of spinlock_check() function?
There should be some meaning but I can't figure it out.
What you are missing is that spinlock_check() does not perform any check at run time. That's why its returned value is ignored. This instruction is expected to be removed during compilation by the optimizer.
Is it of any use, then? Yes! It's purpose is to ensure at compile time that the type of its parameter is spinlock_t *. If you don't give a pointer to spinlock_t as a parameter to spin_lock_init(), you will trigger a compilation error.
I often write code which ends up being long sequences something like
int error;
error = do_something();
if (error) {
return error;
}
error = do_something_else(with, some, args);
if (error) {
return error;
}
error = do_something_yet_again();
if (error) {
return error;
}
return 0;
I'm searching for a cleaner way to write this that to some extent avoids the repeated identical checks. So far, I've written an ERROR_OR macro, which works something like
#define ERROR_OR(origerr, newerr) \
({ \
int __error_or_origerr = (origerr); \
(__error_or_origerr != 0) \
? __error_or_origerr \
: (newerr); \
})
which allows the original code to become something like
int error = 0;
error = ERROR_OR(error, do_something());
error = ERROR_OR(error, do_something_else(with, some, args));
error = ERROR_OR(error, do_something_yet_again());
return error;
This is (in my opinion) a little cleaner. It's also less understandable, since the function of the ERROR_PRESERVE macro isn't apparent unless you read its documentation and/or implementation. It also doesn't solve the problem of repetition, just makes it easier to write all the (now implicit) checks on a single line.
What I'd really like to re-write this all as would be the following:
return ERROR_SHORT_CIRCUIT(
do_something(),
do_something_else(with, some, args),
do_something_yet_again()
);
The hypothetical ERROR_SHORT_CIRCUIT macro would
Take a variable number of expressions in its argument list
Evaluate each expression in order
If every expression evaluates to zero, evaluate to zero itself
If any expression evaluates to nonzero, immediately terminate and evaluate to the value of that last expression
This last condition is where my short-circuit diverges from a straightforward use of the || operator -- since this will evaluate to 1 instead of the error value.
My initial attempt at writing this is the following:
#define ERROR_SHORT_CIRCUIT(firsterr, ...) \
({ \
int __error_ss_firsterr = (firsterr); \
(__error_ss_firsterr != ERROR_NONE) \
? __error_ss_firsterr \
: ERROR_SHORT_CIRCUIT(__VA_ARGS__); \
})
This has two obvious problems:
It doesn't handle its base-case (when __VA_ARGS__ is a single value)
C doesn't support recursive macros
I've looked into some recursive macro hacks, but I dislike using that degree of pre-processor magic -- too much room for something to be subtly wrong. I've also considered using real (possibly variadic) functions, but this would require either
giving up the short-circuit behavior
passing the functions in as pointers, and therefore normalizing their signatures
and both of these seem worse than the original, explicit code.
I'm interested to hear advice on the best way to handle this. I'm open to many different approaches, but my ultimate goal is to avoid repetition without hurting readability.
(I suppose it's obvious I'm suffering some envy of the behavior of the || operator in languages like Ruby).
I'd use code like:
if ((error = do_something()) != 0 ||
(error = do_something_else(with, some, args)) != 0 ||
(error = do_something_yet_again()) != 0)
return error;
return 0;
It's fully defined because there are sequence points before each || operator. It doesn't really need a macro. It only runs into problems when you allocate resources or do other operations between function calls, but that is different from what your example code shows. At least 90% of the battle was creating the sequence of do_something_or_other() functions that make it easy to handle the error sequencing.
Another option:
int error = 0;
do {
// Note: extra parens suppress assignment-as-conditional warning
if ((error = do_something())) break;
if ((error = do_something_else())) break;
if ((error = do_yet_another_thing())) break;
error = do_a_final_thing();
} while (0);
return error;
I'm working with a large SDK codebase glommed together from various sources of varying quality / competence / sanity from Linus Torvalds to unidentified Elbonian code slaves.
There are an assortment of styles of code, some clearly better than others, and it's proving an interesting opportunity to expand my knowledge / despair for the future of humanity in alternate measures.
I've just come across a pile of functions which repeatedly use a slightly odd (to me) style, namely:
void do_thing(foo)
{
do {
if(this_works(foo) != success)
break;
return(yeah_cool);
} while (0);
return(failure_shame_death);
}
There's nothing complicated being done in this code (I haven't cut 10,000 lines of wizardry out for this post), they could just as easily do:
if(this_works(foo) == success)
return(yeah_cool);
else
return(failure_shame_death);
Which would seem somehow nicer / neater / more intuitive / easier to read.
So I'm now wondering if there is some (good) reason for doing it the other way, or is it just the way they always do it in the Elbonian Code Mines?
Edit: As per the "possible duplicate" links, this code is not pre-processed in any sort of macro, it is just in the normal code. I can believe it might be due to a coding style rule about error checking, as per this answer.
Another guess: maybe you didn't quote the original code correctly? I have seen the same pattern used by people who want to avoid goto: they use a do-while(0) loop which at the end returns a success value. They can also break out of the loop for the error handling:
int doXandY() {
do {
if (!x()) {
break;
}
if (!y()) {
break;
}
return 0;
} while( 0 );
/* Error handling code goes here. */
globalErrorFlag = 12345;
return -1;
}
In your example there's not much point to it because the loop is very short (i.e. just one error case) and the error handling code is just a return, but I suspect that in the real code it can be more complex.
Some people use the do{} while(0); construct with break; inside the loop to be compliant in some way with MISRA rule 14.7. This rule says that there can be only single enter and exit point in the function. This rule is also required by safety norm ISO26262. Please find an example function:
int32_t MODULE_some_function(bool first_condition,bool second_condition)
{
int32_t ret = -1 ;
do
{
if(first_condition)
{
ret = 0 ;
break ;
}
/* some code here */
if(second_condition)
{
ret = 0 ;
break ;
}
/* some code here */
} while(0) ;
return ret ;
}
Please note however that such a construct as I show above violates different MISRA rule which is rule 14.6. Writing such a code you are going to be compliant with one MISRA rule, and as far as I know people use such a construct as workaround against using multiple returns from function.
In my opinion practical usage of the do{}while(0); construct truely exist in the way you should construct some types of macros.Please check below question, it was very helpful for me :
Why use apparently meaningless do-while and if-else statements in macros?
It's worth notice also that in some cases do{}while(0); construct is going to be completely optimized away if you compile your code with proper optimization option.
Hm, the code might be preprocessed somehow. The do { } while(0) is a trick used in preprocessor macros; you can define them like this:
#define some_macro(a) do { whatever(); } while(0)
The advantage being that you can use them anywhere, because it is allowed to put a semicolon after the while(0), like in your code above.
The reason for this is that if you write
#define some_macro(a) { whatever(); }
if (some_condition)
some_macro(123);
else
printf("this can cause problems\n");
Since there is an extra semicolon before the else statement, this code is invalid. The do { ... } while(0) will work anywhere.
do {...} while(0) arranged with "break" is some kind of "RAII for Plain C".
Here, "break" is treated as abnormal scope exit (kind of "Plain C exceptions"), so you can be sure that there is only one place to deallocate a resource: after a "while(0)". It seems slightly unusual, but actually it's very common idiom in the world of plain C.
I would guess that this code was originally written with gotos for error handling:
void do_thing(foo)
{
if(this_works(foo) != success)
goto error;
return(yeah_cool);
error:
return(failure_shame_death);
}
But at some point an edict came down from on high "thou shalt not use goto", so someone did a semi-automatic translation from goto style to loop-break style (perhaps with simple script). Probably when the code was merged/moved from one project to another.