Error when trying to cast double to char * [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
My project is to scan an address space (which in my case is 0x00000000 - 0xffffffff, or 0 - (232)-1) for a pattern and return in an array the locations in memory where the pattern was found (could be found multiple times).
Since the address space is 32 bits, i is a double and max is pow(2,32) (also a double).
I want to keep the original value of i intact so that I can use that to report the location of where the pattern was found (since actually finding the pattern requires moving forward several bytes past i), so I want temp, declared as char *, to copy the value of i. Then, later in my program, I will dereference temp.
double i, max = pow(2, 32);
char *temp;
for (i = 0; i < max; i++)
{
temp = (char *) i;
//some code involving *temp
}
The issue I'm running into is a double can't be cast as a char *. An int can be; however, since the address space is 32 bits (not 16) I need a double, which is exactly large enough to represent 2^32.
Is there anything I can do about this?

In C, double and float are not represented the way you think they are; this code demonstrates that:
#include <stdio.h>
typedef union _DI
{
double d;
int i;
} DI;
int main()
{
DI di;
di.d = 3.00;
printf("%d\n", di.i);
return 0;
}
You will not see an output of 3 in this case.
In general, even if you could read other process' memory, your strategy is not going to work on any modern operating system because of virtual memory (the address space that one process "sees" doesn't necessarily (in fact, it usually doesn't) represent the physical memory on the system).

Never use a floating point variable to store an integer. Floating point variables make approximate computations. It would happen to work in this case, because the integers are small enough, but to know that, you need intimate knowledge of how floating point works on a particular machine/compiler and what range of integers you'll be using. Plus it's harder to write the program, and the program would be slower.
C defines an integer type that's large enough to store a pointer: uintptr_t. You can cast a pointer to uintptr_t and back. On a 32-bit machine, uintptr_t will be a 32-bit type, so it's only able to store values up to 232-1. To express a loop that covers the whole range of the type including the first and last value, you can't use an ordinary for loop with a variable that's incremented, because the ending condition requires a value of the loop index that's out of range. If you naively write
uintptr_t i;
for (i = 0; i <= UINTPTR_MAX; i++) {
unsigned char *temp = (unsigned char *)i;
// ...
}
then you get an infinite loop, because after the iteration with i equal to UINTPTR_MAX, running i++ wraps the value of i to 0. The fact that the loop is infinite can also be seen in a simpler logical way: the condition i <= UINTPTR_MAX is always true since all values of the type are less or equal to the maximum.
You can fix this by putting the test near the end of the loop, before incrementing the variable.
i = 0;
do {
unsigned char *temp = (unsigned char *)i;
// ...
if (i == UINTPTR_MAX) break;
i++;
} while (1);
Note that exploring 4GB in this way will be extremely slow, if you can even do it. You'll get a segmentation fault whenever you try to access an address that isn't mapped. You can handle the segfault with a signal handler, but that's tricky and slow. What you're attempting may or may not be what your teacher expects, but it doesn't make any practical sense.
To explore a process's memory on Linux, read /proc/self/maps to discover its memory mappings. See my answer on Unix.SE for some sample code in Python.
Note also that if you're looking for a pattern, you need to take the length of the whole pattern into account, a byte-by-byte lookup doesn't do the whole job.

Ahh, a school assignment. OK then.
uint32_t i;
for ( i = 0; i < 0xFFFFFFFF; i++ )
{
char *x = (char *)i;
// Do magic here.
}
// Also, the above code skips on 0xFFFFFFFF itself, so magic that one address here.
// But if your pattern is longer than 1 byte, then it's not necessary
// (in fact, use something less than 0xFFFFFFFF in the above loop then)

The cast of a double to a pointer is a constraint violation - hence the error.
A floating type shall not be converted to any pointer type. C11dr §6.5.4 4
To scan the entire 32-bit address space, use a do loop with an integer type capable of the [0 ... 0xFFFFFFFF] range.
uint32_t address = 0;
do {
char *p = (char *) address;
foo(p);
} while (address++ < 0xFFFFFFFF);

Related

Use of uninitialised value of size 8 Valgrind

I'm getting
==56903== Use of uninitialised value of size 8
==56903== at 0x1000361D1: checkMSB (in ./UnittestCSA)
==56903== by 0x10003732A: S_derive_k1_k2 (in ./UnittestCSA)
Code is as follows:
int32_t checkMSB(uint8_t *pKey){
int8_t msb = 0;
int32_t ret = 0;
msb = 1 << (8 - 1);
/* Perform bitwise AND with msb and num */
if(pKey[0] & msb){
ret = 1;
} else {
ret = 0;
}
return ret;
}
Not sure what is causing the issue.
If this
#define BITS (sizeof(int8_t) * 8)
is changed to this
#define BITS (sizeof(int) * 8)
it doesn't complain. I have #include <stdint.h> header file.
UPDATE
uint8_t localK1[BLOCKSIZE];
for(index = 0; index < inputLen; index++){
localK1[index] = pInputText[index];
}
result = checkMSB(localK1);
Your checkMSB function declares only two local variables and one function parameter. The variables both have initializers, and the parameter (a pointer) will receive a value as a result of the function call, supposing that a correct prototype for it is in scope at the point of the call. Thus, none of these is used uninitialized.
The only other data that are used (not counting constants), are those pointed to by the argument, pKey. Of those, your code uses pKey[0]. That it is Valgrind reporting the issue supports the conclusion that that's the data it is complaining about: valgrind's default memcheck service watches dynamically allocated memory, and that's the only thing involved that might be dynamically allocated.
That the error disappears when you change the definition of BITS could be explained by the expression pKey[0] & msb being optimized away when BITS evaluates to a value larger than 8.
As far as your update, which purports to show that the function's argument in fact points to initialized data, I'm inclined to think that you're looking in the wrong place, or else in the right place but at the wrong code. That is, there probably is either a different call to checkMSB that causes Valgrind to complain, or else the binary being tested was built from a different version of the code. I'm not prepared to believe that everything you've presented in the question is true, or at least not that it fits together the way you seem to be saying it does.

Don't fully understand custom-written 'memcpy' function in C

So I was browsing the Quake engine source code earlier today and stumbled upon some written utility functions. One of them was 'Q_memcpy':
void Q_memcpy (void *dest, void *src, int count)
{
int i;
if (( ( (long)dest | (long)src | count) & 3) == 0 )
{
count>>=2;
for (i=0 ; i<count ; i++)
((int *)dest)[i] = ((int *)src)[i];
}
else
for (i=0 ; i<count ; i++)
((byte *)dest)[i] = ((byte *)src)[i];
}
I understand the whole premise of the function but I don't quite understand the reason for the bitwise OR between the source and destination address. So the sum of my questions are as follows:
Why does 'count' get used in the same bitwise arithmetic?
Why is that result's last two bits checked if they are differing?
What purpose does this whole check serve?
I'm sure it's something obvious but please excuse my ignorance because I haven't really delved into the more low level side of things when it comes to programming. I just find it interesting and want to learn more.
It is finding out whether the source and destination pointers are int aligned, and whether the count is an exact int size of bytes.
If those three things are all true, the l.s. 2 bits of them all will be 0 (assuming pointers and int are 4 bytes). So the algorithm ORs the three values, and isolates the l.s. 2 bits.
In this case, it copies int by int. Otherwise it copies char by char.
If the test fails, a more sophisticated algorithm would copy some of the leading and trailing bytes char by char and the intermediate bytes int by int.
The bitwise ORing and ANding with 3 is to check whether the source, destination and count are divisible by 4. If they are, the operation can work with 4-byte words, while this code is assuming int as 4 bytes. Otherwise the operation is performed bytewise.
It first tests if all 3 arguments are divisible by 4. If - and only if - they all are, it proceeds with copying 4 bytes at a time.
I.e. this undecoded would be
if ((long) src % 4 == 0 && (long) dst % 4 == 0 && count % 4 == 0 )
{
count = count / 4;
for (i = 0; i < count; i++)
((int *)dest)[i] = ((int *)src)[i];
}
I am not sure if they tested their compiler and it generated bad code for even a test, and therefore they decided to write it in such a convoluted way. In any case, the x | y | z will guarantee that a bit n is set in the result if it is set in any of x, y or z. Therefore if the (x | y | z) & 3 results in 0, none of the numbers had either of the 2 lowest bits set, and therefore are divisible by 4.
Of course it would be rather silly to use now - the standard library memcpy in recent library implementations is almost certainly better than this.
Therefore, on recent compilers you can optimize all calls to Q_memcpy by switching them to memcpy. GCC could generate things like 64-bit or SIMD moves with memcpy depending on the size of area to be copied.

Why won't these two functions convert decimals to binary (uint8_t)? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have two functions which supposedly can convert decimals to binary, however I can't seem to get them to work if the decimal is above 3 (I get weird negative numbers). I can't fully understand the code in the functions as I've only just started to learn C, however I was hoping if someone could tell me if the functions work, or if I am just not doing something right i.e. should I be using int32_t type as the value to pass into the function?
uint8_t dec_to_bin(int decimal){
int n = decimal, i, j, binno=0,dn;
dn=n;
i=1;
for(j=n;j>0;j=j/2)
{
binno=binno+(n%2)*i;
i=i*10;
n=n/2;
}
return binno;
}
uint8_t dec_to_bin2(int decimal){
long long binaryNumber = 0;
int remainder, i = 1;
while (decimal!=0){
remainder = decimal%2;
decimal /= 2;
binaryNumber += remainder*i;
i *= 10;
}
return binaryNumber;
}
Unfortunately I have no way to find out the values of the binary numbers as a uint_8 type as I am doing this on a micro-controller and there is no way to debug or print values anywhere (I have posted numerous threads asking how to do this, with no luck). We have however been provided with another function:
int bin_to_dec(uint64_t binary) {
int result = 0;
for ( int i = 7; i >= 0; i-- ) {
result = result * 10 + ((binary >> i) & 1);
}
return result;
}
This function converts the binary number back to an integer so I can display it on the screen with a library function (the library function can only display integers or strings). If I pass 10 into either of the decimal to binary converter functions, then pass the uint_8 value from either function to the binary to decimal converter and print to the LCD, I get -3110. This should just be 1010.
I'm sorry to say, but your dec_to_bin and dec_to_bin2 functions are meaningless. Throw them away. They might -- might -- have a tiny bit of value as a teaching exercise. But if you're trying to write actual code for a microcontroller to actually do something, you don't need these functions, and you don't want these functions. (Also you need to understand why you don't need these functions.)
The problem is not that they're implemented wrongly. They're fundamentally flawed in their very intent.
These functions seem to convert, for example, the integer 5 to the integer 101, and at first glance that might look like "decimal to binary conversion", but it's not. You've just converted the number five to the number one hundred and one.
Let's look at this a different way. If I say
int i = 17;
and if I then call
printf("%d\n", i);
I see the value "17" printed, as I expect. But I can also call
printf("%x\n", i);
and this prints i's value in hexadecimal, so I see "11". Did I just convert i from decimal to hexadecimal? No, I did not! I took the same number, "seventeen", and I printed it out in two different ways: in decimal, and in hexadecimal.
For all practical purposes, unless you're designing the actual hardware a program will run on, it really doesn't make sense to ask what base a number is stored in. A variable like int i is just a number, an integer. (Deep down inside, of course, on a conventional processor we know it's stored in binary all the time.)
The only time it makes sense to explicitly convert a number to binary is if you want to print it out in a human-readable text representation, in binary. In that case, you're converting from an integer to a string. (The string will consist of the characters '0' and '1'.)
So if you want to write a meaningful decimal-to-binary converter (which will actually be an anything-to-binary converter), either have it print the binary number out to the screen, or store it in a string (an array of characters, or char []).
And if you're in a class where you're being asked to write uint8_t dec_to_bin(int decimal) (or where your instructor is giving you examples of such functions), I can't help you, and I'm afraid you're doomed. Half of what this instructor is teaching you is wrong or badly misleading, will seriously handicap you from ever being a successful C programmer. Of course I can't tell you which half, because I don't know what other lies you're being taught. Good luck -- you'll need it! -- unlearning these false facts later.
I don't know why you're trying to store binary data as base 10 numbers instead of just printing or storing (as a char[]) the bits of an int (get kth bit of n as (n >> k) & 1 then print/store), but I'll assume it's necessary.
Your solution could be prone to overflowing the uint8_t as mentioned in the comments. Even a uint64_t can only hold 19 bits of binary data in the format you're using, less than the 32 of typical ints. The return type of your second function is still uint8_t, this might just be a typo, but it means the internal representation of long long will be implicitly cast on return.
I've written some functions based on yours, but with a little more bit manipulation that work for me.
uint64_t dec_to_bin (int n)
{
uint64_t result = 0;
int k, i;
// 64 bits can only hold 19 (log10(2^64)) bits in this format
for (i = 0, k = n; k && i < 19; i++) {
// Because the loop is limited to 19 we shouldn't need to worry about overflowing
result *= 10;
result += (n >> i) & 1;
k /= 2;
}
return result;
}
int bin_to_dec (uint64_t n)
{
int result = 0;
while (n) {
result <<= 1;
result += n % 2;
n /= 10;
}
return result;
}
I tested your functions on the input 43 on my system and got
43 // Original Input
101011 // dec_to_bin2 with long long return type
10010011 // bin_to_dec
With an appropriately sized output, your dec_to_bin2 function does work as expected.
And my functions:
43 // Original Input
110101 // dec_to_bin
43 // bin_to_dec
The endianness may not be what you're expecting, but that can be changed if necessary.

I need help understanding this code in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm studying C in school and I had this question, and I'm having trouble solving it.
What does the following code do?
#define N (100)
int main(void)
{
unsigned short i = 0;
unsigned long arr[2*N + 1];
unsigned long a = 0;
for (i = 0 ; i < N ; ++i) {
a ^= arr[i];
}
printf("%lu", a);
return 0;
}
It would be really helpful if you could explain it to me!
Thanks!
It's usually a good idea to explain what you understand, so we don't have to treat you as though you know nothing. Important note: This code behaves erratically. I'll discuss that later.
The exclusive or operator (^) produces its result by applying the following pattern to the binary representation of the numbers in question:
Where both operands (sides of the operator) contain different bits, the result will contain a 1 bit. For example, if the left hand side contains a right-most bit of 0 and the right hand side contains a right-most bit of 1, then the result will contain a right-most bit of 1.
Where both operands (sides of the operator) contain the same bit, the result will contain a 0.
So as an example, the operands of 15 ^ 1 have the following binary notation:
1111 ^
0001
... and the result of this exclusive or operation will be:
1110
Converted back to decimal, that's 14. Xor it with 1 again and you'll end up back at 15 (which is the property the silly xor swap takes advantage of).
The array[index] operator obtains the element within array at the position indicated by index.
The ^= operator is a compound operator. It combines the exclusive or and assignment operators. a ^= arr[i]; is roughly equivalent to a = a ^ arr[i];. That means: Calculate the exclusive or of a and arr[i], and assign it back into a.
for (i = 0 ; i < N ; ++i) /*
* XXX: Insert statement or block of code
*/
This denotes a loop, which will start by assigning the value 0 to i, will repeatedly execute the statement or block of code while i is less than N (100), incrementing i each time.
In summary, this code produces the exclusive or of the first 100 elements of the array arr. This is a form of crude checksum algorithm; the idea is to take a group of values and reduce them to a single value so that you can perform some form of integrity check on them later on, perhaps after they've been trasmited via the internet or an unreliable filesystem.
However, this code invokes undefined behaviour because it uses unspecified values. In order to avoid erratic behaviour such as unpredictable values or segfaults (or worse yet, situations like the heartbleed OpenSSL vulnerability) you need to make sure you give your variables values before you try to use those values.
The following declaration would explicitly initialise the first element to 42, and implicitly initialise all of the others to 0:
unsigned long arr[2*N + 1] = { 42 };
It is important to realise that the initialisation part of the declaration = { ... } is necessary if you want any elements not explicitly initialised to be zeroed.
this function will print unpredictable value.
because of unsigned long arr[2*N + 1]; arr is not initialized and it will have random content based on data on you memory.
a ^= arr[i]; is equal to a = a^arr[i]; so it will do this for multiple times (because of loop) and then it will print it.

How to compare C pointers?

Recently, I wrote some code to compare pointers like this:
if(p1+len < p2)
however, some staff said that I should write like this:
if(p2-p1 > len)
to be safe.
Here,p1 and p2 are char * pointers,len is an integer.
I have no idea about that.Is that right?
EDIT1: of course,p1 and p2 pointer to the same memory object at begging.
EDIT2:just one min ago,I found the bogo of this question in my code(about 3K lines),because len is so big that p1+len can't store in 4 bytes of pointer,so p1+len < p2 is true.But it shouldn't in fact,so I think we should compare pointers like this in some situation:
if(p2 < p1 || (uint32_t)p2-p1 > (uint32_t)len)
In general, you can only safely compare pointers if they're both pointing to parts of the same memory object (or one position past the end of the object). When p1, p1 + len, and p2 all conform to this rule, both of your if-tests are equivalent, so you needn't worry. On the other hand, if only p1 and p2 are known to conform to this rule, and p1 + len might be too far past the end, only if(p2-p1 > len) is safe. (But I can't imagine that's the case for you. I assume that p1 points to the beginning of some memory-block, and p1 + len points to the position after the end of it, right?)
What they may have been thinking of is integer arithmetic: if it's possible that i1 + i2 will overflow, but you know that i3 - i1 will not, then i1 + i2 < i3 could either wrap around (if they're unsigned integers) or trigger undefined behavior (if they're signed integers) or both (if your system happens to perform wraparound for signed-integer overflow), whereas i3 - i1 > i2 will not have that problem.
Edited to add: In a comment, you write "len is a value from buff, so it may be anything". In that case, they are quite right, and p2 - p1 > len is safer, since p1 + len may not be valid.
"Undefined behavior" applies here. You cannot compare two pointers unless they both point to the same object or to the first element after the end of that object. Here is an example:
void func(int len)
{
char array[10];
char *p = &array[0], *q = &array[10];
if (p + len <= q)
puts("OK");
}
You might think about the function like this:
// if (p + len <= q)
// if (array + 0 + len <= array + 10)
// if (0 + len <= 10)
// if (len <= 10)
void func(int len)
{
if (len <= 10)
puts("OK");
}
However, the compiler knows that ptr <= q is true for all valid values of ptr, so it might optimize the function to this:
void func(int len)
{
puts("OK");
}
Much faster! But not what you intended.
Yes, there are compilers that exist in the wild that do this.
Conclusion
This is the only safe version: subtract the pointers and compare the result, don't compare the pointers.
if (p - q <= 10)
Technically, p1 and p2 must be pointers into the same array. If they are not in the same array, the behaviour is undefined.
For the addition version, the type of len can be any integer type.
For the difference version, the result of the subtraction is ptrdiff_t, but any integer type will be converted appropriately.
Within those constraints, you can write the code either way; neither is more correct. In part, it depends on what problem you're solving. If the question is 'are these two elements of the array more than len elements apart', then subtraction is appropriate. If the question is 'is p2 the same element as p1[len] (aka p1 + len)', then the addition is appropriate.
In practice, on many machines with a uniform address space, you can get away with subtracting pointers to disparate arrays, but you might get some funny effects. For example, if the pointers are pointers to some structure type, but not parts of the same array, then the difference between the pointers treated as byte addresses may not be a multiple of the structure size. This may lead to peculiar problems. If they're pointers into the same array, there won't be a problem like that — that's why the restriction is in place.
The existing answers show why if (p2-p1 > len) is better than if (p1+len < p2), but there's still a gotcha with it -- if p2 happens to point BEFORE p1 in the buffer and len is an unsigned type (such as size_t), then p2-p1 will be negative, but will be converted to a large unsigned value for comparison with the unsigned len, so the result will probably be true, which may not be what you want.
So you might actually need something like if (p1 <= p2 && p2 - p1 > len) for full safety.
As Dietrich already said, comparing unrelated pointers is dangerous, and could be considered as undefined behavior.
Given that two pointers are within the range 0 to 2GB (on a 32-bit Windows system), subtracting the 2 pointers will give you a value between -2^31 and +2^31. This is exactly the domain of a signed 32-bit integer. So in this case it does seem to make sense to subtract two pointers because the result will always be within the domain you would expect.
However, if the LargeAddressAware flag is enabled in your executable (this is Windows-specific, don't know about Unix), then your application will have an address space of 3GB (when run in 32-bit Windows with the /3G flag) or even 4GB (when run on a 64-bit Windows system).
If you then start to subtract two pointers, the result could be outside the domain of a 32-bit integer, and your comparison will fail.
I think this is one of the reasons why the address space was originally divided in 2 equal parts of 2GB, and the LargeAddressAware flag is still optional. However, my impression is that current software (your own software and the DLL's you're using) seem to be quite safe (nobody subtracts pointers anymore, isn't it?) and my own application has the LargeAddressAware flag turned on by default.
Neither variant is safe if an attacker controls your inputs
The expression p1 + len < p2 compiles down to something like p1 + sizeof(*p1)*len < p2, and the scaling with the size of the pointed-to type can overflow your pointer:
int *p1 = (int*)0xc0ffeec0ffee0000;
int *p2 = (int*)0xc0ffeec0ffee0400;
int len = 0x4000000000000000;
if(p1 + len < p2) {
printf("pwnd!\n");
}
When len is multiplied by the size of int, it overflows to 0 so the condition is evaluated as if(p1 + 0 < p2). This is obviously true, and the following code is executed with a much too high length value.
Ok, so what about p2-p1 < len. Same thing, overflow kills you:
char *p1 = (char*)0xa123456789012345;
char *p2 = (char*)0x0123456789012345;
int len = 1;
if(p2-p1 < len) {
printf("pwnd!\n");
}
In this case, the difference between the pointer is evaluated as p2-p1 = 0xa000000000000000, which is interpreted as a negative signed value. As such, it compares smaller then len, and the following code is executed with a much too low len value (or much too large pointer difference).
The only approach that I know is safe in the presence of attacker-controlled values, is to use unsigned arithmetic:
if(p1 < p2 &&
((uintptr_t)p2 - (uintptr_t)p1)/sizeof(*p1) < (uintptr_t)len
) {
printf("safe\n");
}
The p1 < p2 guarantees that p2 - p1 cannot yield a genuinely negative value. The second clause performs the actions of p2 - p1 < len while forcing use of unsigned arithmetic in a non-UB way. I.e. (uintptr_t)p2 - (uintptr_t)p1 gives exactly the count of bytes between the bigger p2 and the smaller p1, no matter the values involved.
Of course, you don't want to see such comparisons in your code unless you know that you need to defend against determined attackers. Unfortunately, it's the only way to be safe, and if you rely on either form given in the question, you open yourself up to attacks.

Resources