I am working on an encryption project and I am making a simple test that takes a file name from terminal and runs my encryption. I have the following encryption code but I get the following segmentation fault:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid<br><br>
Program received signal SIGABRT, Aborted.
0x00007ffff74ab428 in __GI_raise (sig=sig#entry=6)
at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
After running a trace with gdb I have confirmed that this fault is triggered after the following loc:
string plain(reinterpret_cast(fileContents), fileLength);
My main function below calls this piece of code:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <fstream>
#include <limits>
#include <sstream>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "rc4_enc.c"
#include "rc4_skey.c"
using namespace std;
void foo(int);
int main(int argc, char * argv[]){
if(argc!=2){
cout << "Please enter the filename that you want to encrypt or decrypt\n";
exit(2);
}
int fd;
fd = open(argv[1], O_RDONLY);
cout << "The file descriptor is " << fd << endl;
//close(fd);// Can I modify it if it's closed?
foo(fd);
return 0;
}
And the function is as follows:
void foo(int fd) {
int fileLength = lseek(fd, 0, SEEK_END);
unsigned char* fileContents;
fileContents = (unsigned char*) calloc(fileLength, sizeof(char));
pread(fd, fileContents, fileLength, 0);
string plain(reinterpret_cast<char*>(fileContents), fileLength); // Segfault happens here. But why?
RC4_KEY key;
int length = plain.size();
unsigned char *buf = (unsigned char*)malloc(length+1);
memset(buf, 0, length+1);
ifstream pass;
pass.open("pass.txt");
if(!pass.good()){
return;
}
else{
string password;
getline(pass,password);
RC4_set_key(&key, password.length(), (const unsigned char*)password.c_str());
}
RC4(&key, length, (const unsigned char*)plain.c_str(), buf);
string result((char*)buf, length);
free(buf);
const char *outputBuf = result.c_str();
pwrite(fd, outputBuf, result.length(), 0);
ftruncate(fd, result.length());
}
I would leave this as a comment, but do not have enough reputation.
How large is the file? Could calloc be failing and returning NULL?
Even if it's not that, might be wise to check calloc's return value. Or use the new operator, with try/catch.
Related
I know there is one in C, Sleep(ms), but is there one for C++? I am trying to return an error, then print to the console, then sleep enough for the user to read it before returning the errorcode. Code in C would be:
#include <stdio.h>
#include <windows.h>
int main (int argc, const char *argv[]) {
char *err = "Have an error!";
printf("Error: %s. Program terminating in 5 seconds...", err);
Sleep(5000);
return 1;
}
You could include <windows.h> and just call the WinApi function Sleep just as you would from C. This is mostly pure C++ :
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
using namespace std;
int main (int argc, const char *argv[]) {
string err = "Have an error!";
cout << "Error: " << err << ". Program terminating in 5 seconds..." << endl;
std::chrono::milliseconds timespan(5000);
std::this_thread::sleep_for(timespan);
return 1;
}
on assignment I need to write a program which opens a channel pipe and gives rise to two descendant process and then the parent fills the channel from the input file and then sends the signal SIGQUIT to the descendants, who can read character from channel and send each other signals after reading the next symbol of SIGUSR1 and SIGUSR2 to another descendant was able to start reading, but there was a problem: in a loop reading the parent is stupor, and if debajo the steps then everything is fine and it exits the loop, or if the clean lines of the exec, then exit from the loop occurs. I don't understand what the problem might be. In descendants, I use sigwait to wait. I will present the codes of the parent and descendants below. Please tell me what's wrong? The code of the parent:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <cstring>
#include <sys/wait.h>
#include <signal.h>
#include <wait.h>
using namespace std;
int main() {
sigset_t new_mask;
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGUSR1);
sigaddset(&new_mask, SIGUSR2);
sigaddset(&new_mask, SIGQUIT);
sigprocmask(SIG_SETMASK, &new_mask, NULL);
int fildes[2];
pipe(fildes);
pid_t pid1;
pid_t pid2;
pid1 = fork();
if (pid1 == 0) {
//execl("1","1", "output1.txt", &fildes[0], &fildes[1],NULL);
close(fildes[0]);
_exit(0);
}
else {
pid2 = fork();
if (pid2 == 0) {
execl("2","2", "output2.txt", &fildes[0], &fildes[1], NULL);
close(fildes[0]);
_exit(0);
}
else {
close(fildes[0]);
cout<<"Parent"<<endl;
ifstream file("input.txt");
if (file.is_open()) {
string str;
bool t = true;
t = (bool)getline(file, str);
while(t){
write(fildes[1], &str[0], strlen(str.c_str()));
cout<<"PARENT пишет:" << str << endl;
cout<< "sdsdsds";
t = (bool)getline(file, str);
}
cout << "aaaaaaaaaaaaaaaaaaaaaaaaa";
killpg(0, SIGQUIT);
file.close();
}
int st1, st2;
waitpid(pid1, &st1, 0);
waitpid(pid2, &st2, 0);
close(fildes[1]);
exit(EXIT_SUCCESS);
}
}
return 0;
}
First child's code:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <cstring>
#include <sys/wait.h>
#include <signal.h>
#include <wait.h>
#include <cerrno>
using namespace std;
int main(int argc, char** argv) {
int fildes[2];
fildes[0]=*argv[2];
fildes[1]=*argv[3];
close(fildes[1]);
sigset_t mask_sig;
sigemptyset(&mask_sig);
sigaddset(&mask_sig, SIGUSR1);
sigaddset(&mask_sig, SIGQUIT);
ofstream file;
int last_sig;
char ch;
file.open(argv[1], ios::app);
//file << read(fildes[0], &ch, 1) << endl;
sigwait(&mask_sig, &last_sig);
while(read(fildes[0], &ch, 1) > 0){
//file << "a" << endl;
file << ch;
killpg(0, SIGUSR2);
sigwait(&mask_sig, &last_sig);
}
killpg(0, SIGUSR2);
file.close();
return 0;
}
Second child's code:
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <cstring>
#include <sys/wait.h>
#include <signal.h>
#include <wait.h>
using namespace std;
int main(int argc, char** argv) {
int fildes[2];
fildes[0]=*argv[2];
fildes[1]=*argv[3];
close(fildes[1]);
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGQUIT);
sigset_t mask_sig;
sigemptyset(&mask_sig);
sigaddset(&mask_sig, SIGUSR2);
ofstream file;
int last_sig;
char ch;
file.open(argv[1], ios::app);
//sigwait(&mask, &last_sig);
sigwait(&mask_sig, &last_sig);
while(read(fildes[0], &ch, 1) > 0){
file << ch;
killpg(0, SIGUSR1);
sigwait(&mask_sig, &last_sig);
}
killpg(0, SIGUSR1);
file.close();
return 0;
}
This question already has answers here:
Different answers from strlen and sizeof for Pointer & Array based init of String [duplicate]
(4 answers)
Closed 3 years ago.
I'm trying to write out data that the user entered into argv[2]. I have to use write() system call (unix)
for Example I enter "hi there" but "hi th" is written out into the file instead of the whole text.
#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
using namespace std;
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
int fd, fileWrite;
char *file = argv[1]; //file to be create
char *text = argv[2]; //text stored here
fd = open(file, O_WRONLY | O_APPEND | O_CREAT);
//write message from command line
fileWrite = write(fd, text, sizeof(text));
fileWrite = write(fd, "\n", 1);
if(fileWrite == -1){
perror("fileWrite");
}
//close file
close(fd);
return 0;
}`
Use strlen(text) in<string.h> instead of sizeof(text) to determine the length of the string, sizeof(text) will return you the size of a pointer, which is always the same.
I have the following program which reads a file into a string buffer.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
constexpr int BUFSIZE = 1024;
int main(int argc, char *argv[])
{
std::ifstream ifs(argv[1], std::ifstream::binary);
if(!ifs)
return 1;
string buffer(BUFSIZE, L'\0');
ifs.read(&buffer[0], BUFSIZE);
cerr << ifs.gcount() << endl;
return 0;
}
It prints out the expected 1024.
The following program which is supposed to read into a wstring buffer doesn't work though.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
constexpr int BUFSIZE = 1024;
int main(int argc, char *argv[])
{
std::wifstream ifs(argv[1], std::ifstream::binary);
if(!ifs)
return 1;
wstring buffer(BUFSIZE, L'\0');
ifs.read(&buffer[0], BUFSIZE);
cerr << ifs.gcount() << endl;
return 0;
}
Ir prints out 0 with the same file.
As you can see the only difference is changing the stream to a wstream and the buffer to a wstring.
I've tried both g++ 8.2.1 and clang++ 6.0.1 under OpenSUSE Tumbleweed.
Where is the problem/my error?
You should be using std::basic_ifstream<char16_t> and std::u16string for UTF-16. std::wifstream and std::wstring are not appropriate because the width of wchar_t is implementation defined. In Linux in particular, it is (usually?) 32 bits wide.
Same for character literals. You should use u'\0' etc. instead of L'\0'.
I have a server and a client program. Server program prompts user to enter text, then sends user input to client. The client prints out user text to screen. So far server program prompts user to enter text and when I run client program it displays nothing. Any recommendations to make programs work. Below are both programs.
// server.cpp
// g++ -o server server.cpp -lpthread -lrt
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>
#include <ctype.h>
#include <iostream>
using namespace std;
string UserInput(string);
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main(void)
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
string input;
//name the shared memory segment
key = 1000;
//create & initialize semaphore
mutex = sem_open(SEM_NAME,O_CREAT,0644,1);
if(mutex == SEM_FAILED)
{
perror("unable to create semaphore");
sem_unlink(SEM_NAME);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,IPC_CREAT|0666);
if(shmid<0)
{
perror("failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = (char*) shmat(shmid,NULL,0);
//start writing into memory
s = shm;
// Enter user input
//cout << "Enter your input: ";
//cin >> input;
// Display user input
//cout << "You entered: "<< input << endl;
//return 0;
while(1)
{
cout << "Enter your input: ";
cin >> input;
sem_wait(mutex);
//*s++ = count;
sem_post(mutex);
//return 0;
}
//the below loop could be replaced by binary semaphore
while(*shm != '*')
{
sleep(1);
}
sem_close(mutex);
sem_unlink(SEM_NAME);
shmctl(shmid, IPC_RMID, 0);
_exit(0);
}
-
// client.cpp
// g++ -o client client.cpp -lpthread -lrt
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <ctype.h>
using namespace std;
string UserInput(string);
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main(void)
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
string input;
//name the shared memory segment
key = 1000;
//create & initialize existing semaphore
mutex = sem_open(SEM_NAME,0,0644,0);
if(mutex == SEM_FAILED)
{
perror("reader:unable to execute semaphore");
sem_close(mutex);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,0666);
if(shmid<0)
{
perror("reader:failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = (char*) shmat(shmid,NULL,0);
//start reading
s = shm;
while(1)
{
cout << "You entered: " << input << endl;
//cin >> input;
sem_wait(mutex);
putchar(*s);
sem_post(mutex);
return 0;
}
//once done signal exiting of reader:This can be replaced by another semaphore
*shm = '*';
sem_close(mutex);
shmctl(shmid, IPC_RMID, 0);
exit(0);
}