Part 6 - Basic I/O
For a complete table of contents of all the lessons please click below as it will give you a brief of each lesson in addition to the topics it will cover. https://github.com/mytechnotalent/hacking\_c-\_arm64
Today we are going to look at a basic I/O C++ program that has some minimal validation.
Before I get into the brief lecture as I try to keep these short, I wanted to explain why I am not using the textbook straight cin examples that you see across the globe.
The cin, standard input stream, which takes input from the keyboard is referred to as our stdin.
What cin does is use whitespace, tab and newline as a terminator to the input stream. For example if you input 'abc' and hit a tab or put a whitespace or newline by hitting return the data to the right of it will be ignored.
The problem is if you read from cin again it will pick up the remaining data in the stream if you do not flush the input buffer.
If you had for example:
std::cin >> val1; std::cin >> val2;
If the user enters 1 and then leaves a space and then 2 and presses enter, you have no issue. 1 will be assigned into val1 and 2 will be assigned to val2 as they are chained.
The problem is what if you enter 'Hey Jude' instead of an integer? What happens is it tries to read an integer and it goes into a failed state and from that point everything else it is extracting is unreliable.
I did not mean to be long winded but I really wanted to emphasize why you would NEVER use cin by itself and I mean NEVER!
Let's take a look at our basic i/o program that we will debug in the next lesson with a very basic C++ program that validates input.
#include <iostream> #include <sstream> #include <string> int main() { int age = 0; bool valid = false; char null = '\0'; while (!valid) { std::cout << "Enter Age: "; // Get input as string std::string line; getline(std::cin, line); // Init stringstream std::stringstream is(line); // Attempt to read a valid age from the stringstream and // if a number can't be read, or there is more than white // space in the string after the number, then fail the read // and get another string from the user and make sure the // dude is at least a year old and less than or equal to // 100 years old if (!(is >> age) || (is >> std::ws && is.get(null)) || age >= 100 || age <= 0) std::cout << "Dude be real!" << std::endl; else valid = true ; } std::cout << "Your are " << age << " years old, seems legit!" << std::endl; return 0; }
We start by importing iostream, sstream and string. So far nothing tricky.
We then prompt the user to enter their age. We then create a string object called line and take advantage of C++ getline() which is a standard C++ library function that is used to read a string or a line from an input stream properly.
We then take advantage of the stringstream as it associates a string object with a stream allowing you to read from the string as if it were a stream like we would do with raw cin. In this simple example we create an is object which is short for input stringstream and connect it with our line object.
Then before we echo data to stdout we do a little validation. We first check to see if age is the type it was defined as which is an int OR is there a white space in the stream after a given integer OR is age greater than 100 or less than 0. Very simply it provides a response if the input does not meet this criteria.
Finally if all is well it echoes out a simple cout.
Let's compile and link.
g++ -o 0x02_asm64_basicio 0x02_asm64_basicio.cpp
Let's run.
./0x02_asm64_basicio
Depending on what you enter it will validate as appropriate as described above. PLEASE try this example and manipulate the source to get a full understanding of what is going on here.
In our next lesson we will debug this very simple binary using our dev build of Radare2.