-2

Error: Cannot convert DWORD* {aka unsigned int*} to 'long unsigned int*' for argument 1 to int tea_encrypt(long unsigned int*,)

Here is the code :

bool CLZObject::Encrypt(DWORD * pdwKey)
{
    if (!m_bCompressed)
    {
        assert(!"not compressed yet");
        return false;
    }

    BYTE * pbBuffer = m_pbBuffer + sizeof(THeader);
    m_pHeader->dwEncryptSize = tea_encrypt((DWORD *) pbBuffer, (const DWORD *) pbBuffer, pdwKey, m_pHeader->dwCompressedSize + 19);
    return true;
}
legends2k
  • 31,634
  • 25
  • 118
  • 222
Irinel Iovan
  • 835
  • 1
  • 8
  • 12
  • What version of C++ are you using? – Tim Biegeleisen Mar 27 '15 at 06:15
  • I try to make a converter with key LZO, a decrypter Iso. I am using c ++ 11 because the CFLAGS we defined -std=c++11 – Irinel Iovan Mar 27 '15 at 06:20
  • 2
    Oh, and don't post pictures of text, and not links (that can go stale) either. – Some programmer dude Mar 27 '15 at 06:21
  • I'm not asking what your whole program is doing, I'm asking what you are trying to do that causes this error. At the very least edit your question to include the relevant code, or better yet create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) and show us. – Some programmer dude Mar 27 '15 at 06:22
  • Now i edited the post, sorry for snipet but i'am new on stack. And i dont't know how to puun code. Thanks – Irinel Iovan Mar 27 '15 at 06:27
  • And finally *read the error message*, It states that you're passing a `unsigned int *` argument to a function that wants a `long unsigned int *`, those two types are not equal, so think about your casting. – Some programmer dude Mar 27 '15 at 06:29
  • Ok, and what it must do. What change do not realize. I am beginner in c ++. What function i must to edit? :(( Honestly, I really do not realize how the function should look like this? – Irinel Iovan Mar 27 '15 at 06:32
  • What compiler are you using actually? On Visual C++ ``DWORD*`` and ``long unsigned int*`` are compatible. It also matters what memory model your platform is using. See [this page](http://en.cppreference.com/w/cpp/language/types). – Chuck Walbourn Mar 27 '15 at 06:37
  • Here is my .cpp file that i want to compile lzo.cpp http://pastebin.com/LKbzneJR And here is lzo.h http://pastebin.com/jURqVyV8 – Irinel Iovan Mar 27 '15 at 06:38
  • Edit code into the question, not links to pastebin. If it's long, reduce it to the smallest complete example of the problem. – Retired Ninja Mar 27 '15 at 06:40
  • Chuck i use g++49, with cygwin. – Irinel Iovan Mar 27 '15 at 06:40
  • why do you actually cast it to `DWORD*` in the first place? if the function takes an `unsigned long int*` it would be more natural to cast it to that. – AndersK Mar 27 '15 at 07:46
  • CyberSpock I'am begginer in c++ as i said. :( Still learning. – Irinel Iovan Mar 27 '15 at 07:50

3 Answers3

2

To understand the problem you're facing, you've to understand that two types, conceptually, are never the same (unless it's just a typedef). int and long are 2 different types according to the language. Although your implementation may have them equally sized, they needn't be the same across all implementations. If you're aiming for portable code, making an assumption that they will be equally sized will lead to issues. How?

Say we've an implementation where sizeof(int) is 4 and sizeof(long) is 8.

int i = 0;
long *l = &i;   // good that the compiler rejects this

If this was allowed, then you'd be getting into undefined behaviour. Say i lives at memory location 2000, since it's 4-byte sized, accessing till 2003 is allowed, since this memory is owned by the program. What lies beyond that is unkown to the program(mer) and is thus inaccessible.

|<------------- i ------------->|
+-------+-------+-------+-------+-------+-------+-------+-------+
| 0x00  | 0x00  | 0x00  | 0x00  |unknown|unknown|unknown|unknown|
+-------+-------+-------+-------+-------+-------+-------+-------+
  2000    2001    2002    2003    2004    2005    2006    2007
|<---------------------------- *l ----------------------------->|  // oops!

Since long is of size 8, making l point to i's address (2000) would mean it'll point to 2000 and if you dereference the pointer i.e. do *l to read what's in there, it'll try to read a long of size 8, there by trying to access 2004 to 2007 additional to reading 2000 to 2003. Thus leading you to undefined behaviour.

Avoid hacks like explicit conversion (type casting), do it the clean way. Use a temporary.

void need_long(long *data) { /* some code */ }

int i = 0;
long l = i;     // temporary long to pass it to need_long
need_long(&l);

If you are OK with not being portable and are confident that int and long are of the same size, on your implementation, you may additionally pass -fpermissive to allow this conversion which GCC prohibits by default.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • 1
    `-fpermissive` rather than `-fpermissible` – Mike Kinghan Mar 27 '15 at 09:26
  • @MikeKinghan You're right, was hasty then! Thank you :) – legends2k Mar 27 '15 at 09:28
  • It seems you posted the code you are trying to compile on pastebin.com at http://pastebin.com/LKbzneJR . It should work as long as you compile it on windows. The problem is caused by the tea code that breaks if compiled as 64-bit code using gcc. (It works with gcc in 32-bit mode (-m32) and Visual C++ in 32-bit mode). Replace `unsigned long` by `unsigned int` everywhere *in the TEA code* to fix your problem, or compile as 32-bit program. – Michael Karcher Mar 27 '15 at 20:38
  • @legends2k In fact, I wanted to post this as a comment below *my* answer, not below your answer. Sorry for the confusion I have caused. Still, the OP obviously found it, and accepted my answer. – Michael Karcher Mar 28 '15 at 17:35
  • Very well, no issues. – legends2k Mar 30 '15 at 15:12
1

Check the function tea_encrypt. It is quite likely that this function expects unsigned long to be 32 bits (as DWORD is on Windows, even on Win64), while unsigned long is likely 64 bits on your system. You should fix that function. The best approach is changing the type unsigned long for the buffer to encrypt to uint32_t to explicitly pin down the 32-bitness of the type. uint32_t * should be compatible to DWORD*, even on your system.

Michael Karcher
  • 3,803
  • 1
  • 14
  • 25
  • Thanks a lot, my tea_encrypt function was defined as unsifned long int. I changed it in unsigned int and now it works Thx all – Irinel Iovan Mar 28 '15 at 08:54
0

From the error message, the first argument of tea_encrypt() is of type long unsigned int *. The (DWORD *) explicitly converts pbBuffer to a unsigned int *.

While it is possible for the long unsigned int and a unsigned int, that is not required by the standard. If they are not equivalent types with your implementation (i.e. compiler in this case) a pointer to one cannot be implicitly converted into a pointer to the other.

An implicit conversion (from unsigned int * to long unsigned int *) is required in order to pass the first argument to the function. The compiler is complaining because that implicit conversion is not permitted.

As to what you do, the obvious would be to replace the (DWORD *) with long unsigned int * (i.e. convert the value of pbBuffer to be a pointer that the function expects). That will get your code to compile.

Whether the code will then behave correctly is another story. You haven't provided enough context for anyone to determine that.

Peter
  • 35,646
  • 4
  • 32
  • 74