Why I got this error passing a array element to crypt() - c

i got 2 error messages for the code, I tried to figure it out myself searching online but it didn´t help. the message are like this:
error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Werror,-Wint-conversion]
strcpy(genHash,crypt( letters[i], "abc"));
the other one is the same message but for passW[0]. I just want to understand what happen. I would appreciate any help. Also if anyone can recommend a good lecture about char arrays, char arrays using pointers. thanks

When you call a function and pass letters[i] or passW[0], you are passing a single character. But it sounds like these functions expect entire strings, that is, arrays of characters.
You might be able to get away with passing letters instead of letters[I], and passW instead of passW[0]. (But it's hard to be sure, because you haven't shown us your code.)

If you want to learn about char arrays and char array pointers then you should grab a copy of 'The C programming language' by Kernighan and Richie. It has a whole chapter on it. It's also a spectacular reference for C in general.
Char variables are actually unsigned 8-bit (1 byte) integers in C/C++. They have values from 0 to 255. When you use fputs() or other print functions in C/C++, these integer values are converted to characters based on your chosen character/type set.
Have you checked the type of the output that crypt() returns? If you're using a genuine GNU compiler then you can use the typeof() function/operator to check the output. Or you could look for the definition of crypt() in your header files. It's possible that it isn't the input to crypt that's causing the problem. It could be nesting crypt() inside strcpy() without an appropriate cast.

Related

Need help figuring out parameters of __isoc9_scanf()

I have some some C code that I'm trying to understand which uses the function __isoc99_scanf(). I haven't encountered that function ever before. I looked it up and it turns out that it is some kind of variation of scanf(). This is the code:
__isoc99_scanf(&DAT_00400d18,local_78,(undefined4 *)((long)puVar3 + 4));
&DAT_00400d18 is a C string containing the value "%s". local_78 is an array of unknown data type. puVar3 is a pointer that points to the last element of that array.
What really confuses me is why does that function call have three parameters? I know that scanf() takes two parameters: the first one is the format string. The second one is the memory address to save the date into. However __isoc99_scanf() here is invoked with three parameters. I cannot understand why the third parameter is there. The first parameter &DAT_00400d18 is just "%s", which suggests that the second parameter be a memory location where to save that string. But why do you need the third parameter when it's not even specified in the format string?
This is not my code, I didn't write it. Actually it is a disassembled version of the assembly code for a particular application that I'm trying to debug. But I've never seen __isoc99_scanf() before because I only used scanf() in my own code.
When you compile scanf, the compiler automatically translates it to the __isoc99_scanf function in libc. If you compile this code:
#include <stdio.h>
int main() {
char buf[32];
scanf("%32s", buf);
return 0;
}
and decompile in GHIDRA, you get:
__isoc99_scanf(&DAT_001007b4,local_38);
where DAT_001007b4 is "%32s" and local_38 is a buffer. It behaves exactly the same as normal scanf. One important thing to keep in mind when using GHIDRA is it doesn't know exactly how many arguments a function should expect, so if a function is being passed in too many arguments, like in your case, you should just ignore the extra arguments since the code will too.

makes pointer from integer without a cast... DS1307, RTC, BCD

I know this question has been asked before. It's all over Google and on this site too, but I can't understand people when they explain it. I have already spent far too many hours trying to understand and I still don't so please try to understand that there's something fundamental I am NOT understanding... here we go.
When programming in C on Proteus, I often get the warning and/or error (in this case warning):
makes pointer from integer without a cast
and I don't get it. Like I said, I've already spent hours looking into it and I get it has to do with types, and/or pointers, blah. Someone please explain it to me like a normal person.
Also, I get this a lot. Could it be possible to get this warning from other types of variables without a cast? A character? How would I go about fixing this problem now, and avoiding it in the future?
Here's the context...
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "stdlib.h"
#include "USART.h"
#include "I2C.h"
#include "ds1307.h"
void Wait()
{
uint8_t i;
for(i=0;i<20;i++)
_delay_loop_2(0);
}
uint8_t ss,mm,hh,dd,nn,yy,x; // Appropriately labeled variables
uint16_t sec[3],min[3],hr[3],day[3],month[3],year[3],mode[2];
uint16_t secs,mins,hrs,days,months,years,modes;
int main(void)
{
_delay_ms(50);
USART_interrupt_init(); //
USART_send('\r'); // Send carriage return
_delay_ms(100); // Allows for the LCD module to initialize
I2CInit(); // Initialize i2c Bus
DS1307Write(0x07,0x10); // Blink output at 1Hz
while(1)
{
int i=0;
/* SECONDS */
DS1307Read(0x00,&ss); // Read seconds address
/* MINUTES */
DS1307Read(0x01,&mm); // Read minutes address
/* HOURS */
DS1307Read(0x02,&hh); // Read hours address
/* DAY */
DS1307Read(0x04,&dd); // Read hours address
/* MONTH */
DS1307Read(0x05,&nn); // Read hours address
/* YEAR */
DS1307Read(0x06,&yy); // Read hours address
for(i=0;i<5;i++)
{Wait();i++;}
sec[0]=(0b00001111 & ss);
sec[1]=((0b01110000 & ss)>>4);
sec[2]='\0';
itoa(sec[0],secs,10);
USART_putstring(secs); // place string in buffer
and the 2 errors:
../main.c:59: warning: passing argument 2 of 'itoa' makes pointer from integer without a cast
../main.c:62: warning: passing argument 1 of 'USART_putstring' makes pointer from integer without a cast
Your compiler is telling you that the function expects a pointer, but you've passed an integer. So it's going to automatically treat your integer value as an address and use that as the pointer.
For example, itoa expects a pointer to a memory location for its second parameter - that's where it stores the resulting string that it builds from the integer you pass it. But you've passed secs for that - a uint16_t. The compiler is warning you that whatever value is in that integer is going to be used as the address where itoa puts its resulting string.
This kind of thing would cause a segfault on most targets, but I'm not familiar with Proteus.
Anyway, as an example, to fix the itoa warning, use something like the following:
char secs[3];
...
itoa(sec[0], secs, 10);
Hope that helps.
So here's a completely different answer to the question, at a much higher level, and to make the point clear, we're going to take a step back from C programming and talk about building houses. We're going to give instructions to the people building the house, but we're going to imagine we have some rigid, codified way of doing it, sort of like function calls.
Suppose it's time to paint the outside of the house. Suppose there's a "function" paint_the_house() that looks like this:
paint_the_house(char *main_color, char *trim_color);
You decide you want white trim on a yellow house, so you "call"
paint_the_house("white", "yellow");
and the painters dutifully paint the house white with yellow trim. Whoops! You made a mistake, and nobody caught it, and now the house is the wrong color.
Suppose there's another function, finish_the_floors() that looks like this:
finish_the_floors(char *floor_material, char *color)
The floor_material argument is supposed to be a string like "hardwood", "carpet", "linoleum", or "tile". You decide you want red tile floors in your house, so you call
finish_the_floors("red", "tile");
But the guy who installs the floors comes back and says, "Listen, buddy, 'red' is not a floor material, and 'tile' is not a color, so do you want to try that again?" This time, someone caught your mistake.
Finally, suppose there's a function
furnish_the_bathroom(char *bath_or_shower, int number_of_sinks)
where bath_or_shower is supposed to be the string "bathtub" or "shower", and the second argument is supposed to be the number of sinks you want. You decide you want two sinks and a bathtub and, continuing your careless ways, you call:
furnish_the_bathroom(2, "bathtub");
This time, your bogus "function call" doesn't even make it to the guy who's going to build the bathtub. The architect's dim-bulb nephew, who his brother conned him into hiring for the summer, who can't even tell the difference between a toaster oven and a two-by-four, he's been put in charge of relaying instructions from you to the laborers, and even he can see that there's something wrong. "Um, wait a minute," he whines. "I thought the first thing was supposed to be a string, and the second thing was supposed to be a number?"
And now we can go back to your question, because that's basically what's going on here. When you call a function, you have to pass the right arguments in the right order (just like your instructions to the builders). The compiler can't catch all your mistakes, but it can at least notice that you're doing something impossibly wrong, like passing an int where you're supposed to pass a pointer.
It means that the compiler implicitly casts it for you, however, it notifies you it did by emitting a warning so you know that.
Here's an example using numbers:
float f = 1.0;
int i = f;
Depending the platform, language and compiler settings a couple of scenarios are possible:
compiler implicitly casts float to int without a warning (bad)
idem but issues a warning (better)
compiler settings changed to treat warnings as errors (safe, security critical etc...)
Warnings are a good hint on possible bugs or errors and it's generally wise to fix them instead of suppressing or ignoring them.
In your specific case, I've been looking for an USART_pustring and the first I've found was this one :
void USART_putstring(char* StringPtr)
No need to look further, passing an int to a function expecting char* (if this is the case), 'might' produce an unexpected result.
Solution
Read the documentation of USART_putstring and ensure you 'transform' your input data to the correct type it accepts, the warning will vanish by itself.
EDIT:
+1 for Aenimated1
Ensure that you understand what are the differences between 'integer' and 'pointer to integer' too, he explained that rather well :)
Integers are for counting. Pointers are an abstract indication of where a variable may be found.
To keep things clear in your head it is a good idea to not mix up the two, even if you are on a system where the concrete implementation of a pointer is the same as the implementation of an integer.
It is an error to convert integer to pointer or vice versa, unless you write a cast to say "I know what I'm doing here".
Unfortunately some compilers will spit out "warning" and then generate a bogus binary. If possible, see if you can use compiler switches that will make the compiler say "error" for this case.
If you see this error it usually means that you supplied an integer where the compiler was expecting you to supply a pointer.
In your code, you do this with itoa(sec[0],secs,10); is a problem. The itoa function signature is:
char * itoa ( int value, char * str, int base );
You supplied secs, which is a uint16_t (a 16-bit integer), for the parameter char * str. This is an error because it expects the address of an object, but you supplied a number.
To fix this you need to stop supplying integers for parameters that are pointers.
For assistance with how to convert the output of DS1307Read to a display string, post a question asking about that specifically.

Safety of using \0 before the end of character arrays

I am writing a driver for an embedded system that runs a custom version of modified linux (Its a handscanner). The manufacturer supplys a custom Eclipse Juno distribution with a few libraries and examples inbound.
The output I receive from the comport comes in form of a standard character array. I am using the individual characters in the array to convey information (error ids and error codes) like this:
if (tmp[i] == 250])
Where tmp is a character array in form of char tmp[500]; that is first initialized to 0 and then filled with input from the comport.
My question is:
Assuming I iterate through every piece of the array, is it safe to use 0 (as in \0) at any point before the end of the Array? Assuming I am:
Not treating it as a string (iterating through and using it like an int array)
In knowledge of what is going to be in there and what exactly this random \0 in the middle of it is supposed to mean.
The reason im asking is because I had several coworkers tell me that I should never ever ever use a character array that contains \0 before the end, no matter the circumstances.
My code doing this currently performs as expected, but im unsure if it might cause problems later.
Rewriting it to avoid this behaviour would be a non-trivial chunk of work.
Using an array of char as an array of small integers is perfectly fine. Just be careful not to pass it to any kind of function that expects "strings".
And if you want to be more explicit about it, and also make sure that the array is using unsigned char you could use uint8_t instead.

Use data type according to command line argument in C

I am trying to save the data type given as a command line argument in my C program and use that type in the whole program without checking it. For example, I could run the program "./name -d int" or "./name -d float" and I want the data type to be saved for further use and to be seen in the entire program, not only in the main() function. A short example:
int main() {
/* read command line argument */
/* I would like to be able to save the type in T to use like this */
T a[20];
/* rest of the program */
}
Could I do this?
Thank you.
As pointed out by an earlier answer, you can't do this in c unless you have something like switch statements in your code that handle different cases, because data types are determined at compile time. If you are willing to settle for less than 64 bit precision for integers and you have 64 bit doubles, you can use doubles for all of your numbers and then just have switch statements e.g. when you output, that convert the double to an integer or char etc. as necessary and then output in the desired format.
No you can't do that in C.
Types have to be determined are compile-time, you can't choose the type at runtime.
More dynamic languages (like Objective-C for instance) will allow you to do such things.
Why are you trying to do that in the first place ? Maybe we can provide any more guidance.

strlen to return size_t?

In C:
My string length function is returning a size_t value?
Why is it not returning a integer which is conventional? And one more thing I noticed was that when I was trying concatenate this string with another string I received a bus error when I ran the program.
Context: I was kind of playing with gmp library and converting big numbers to strings and I end up with the above situation.
What kind of a string is that? Is my operating system playing a role in this issue? I use a MAC, 64-bit OS.
Edited: The error message I received was:
: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘size_t’
Thanks!
#all: Thanks for the answers but I thought I will put the bus error as another question because it seems to be a different issue.
The problem is int might be not wide enough to store the whole range of possible length values. For example on 64-bit you can have a string longer than 4 gigabytes and if int is 32 bit you can't possibly return length of such a long string via an int variable.
strlen() always returned size_t ... and the POSIX standard also says that.
I guess the reason is that int has sign and the capacity of even an unsigned int might not be enough for holding size of an element (say if you have a 32bit int on x86-64 with 16GB RAM) ... the example is extreme, but possible.
POSIX strlen() does return size_t.
As to what's caused the bus error, it's impossible to say without seeing the code and knowing more details about the exact nature of your changes. One possibility is that you've caused a buffer overrun or did something with a NULL pointer you shouldn't have done.
To address your warning (which is actually an error - you've invoked undefined behavior by passing the wrong type to printf) you should use %zu rather than %d for printing size_t values.
strlen() returns a size_t since at least ISO C90 -- I just checked in my copy. And this standard should have no technical difference with ANSI C89.
There was a change of convention (size_t wasn't in K&R C), but it was a long time ago.
There is a very simple and logical reason for all of the functions from the standard library to work with size_t when it comes to lengths of memory blocks - the built-in sizeof operator yields a size_t result as well.
Moreover, size_t is unsigned, of a particular size, tied to the architecture and is semantically different than just a generic int which is meant for storing any number from the count of trees around your office to your SO reputation.

Resources