C Best way to read series of characters without known length - c

I've to read a series of characters that must be brackets but I don't know how many characters the user type. So I think to use realloc each time I've to add the input.
I have to use scanf to read the characters
I wrote this code that works but I want to know if there's a way more secure or simply better.
char* read(void)
{
int count = 0,
valid = 1;
char *str = NULL,
*tmp = NULL;
char input;
printf("Digita sequenza di parentesi da analizzare: ");
do
{
scanf("%c", &input);
tmp = (char *)realloc(str, (++count) * sizeof(char));
if(tmp != NULL)
{
str = tmp;
str[count-1] = input;
/* check sul carattere letto verificando che sia una parentesi (escluso ENTER) */
if((input != '(' &&
input != ')' &&
input != '[' &&
input != ']' &&
input != '{' &&
input != '}' &&
input != '\n') ||
((count == 1) &&
(input == '\n')))
valid = 0;
}
else
{
valid = 0;
free(str);
}
} while(input != '\n');
/* TODO */
/* str[count] = '\0'; */
return (valid) ? str : NULL;
}

I would not suggest doing a realloc at every iteration. Rather use some optimal size buffer at the beginning and then do a realloc only if this size is crossed. Something as below:
#define DEFAULT_STEP_SIZE 64
char* read(void)
{
int count = 0,
valid = 1,
num_alloc = 0;
char *str = NULL,
*tmp = NULL;
char input;
str = malloc(DEFAULT_STEP_SIZE * sizeof(char));
if(str == NULL){
return NULL;
}
num_alloc = 1;
printf("Digita sequenza di parentesi da analizzare: ");
do
{
scanf("%c", &input);
if(count > num_alloc * DEFAULT_STEP_SIZE){
++num_alloc;
tmp = (char *)realloc(str, (num_alloc * DEFAULT_STEP_SIZE) * sizeof(char));
if(tmp == NULL){
free(str);
return NULL;
}else{
str = tmp;
}
}
count++;
str[count-1] = input;
/* check sul carattere letto verificando che sia una parentesi (escluso ENTER) */
if((input != '(' &&
input != ')' &&
input != '[' &&
input != ']' &&
input != '{' &&
input != '}' &&
input != '\n') ||
((count == 1) &&
(input == '\n')))
valid = 0;
} while(input != '\n');
/* TODO */
/* str[count] = '\0'; */
return (valid) ? str : NULL;
}

Related

How to use an array from a different function?

I have a function called readFile, which opens a file, reads the contents, and puts it to an array called 'str'. However, the file is entered by the user as a command line argument, so I can't use that file again in the other function, since it doesn't use a filename parameter. My first function is below:
char *readFile(char *filename) {
FILE *fptr;
long str_length;
char *str;
fptr = fopen(filename, "rb");
fseek(fptr, 0, SEEK_END);
str_length = ftell(fptr);
rewind(fptr);
str = calloc(str_length + 1, sizeof(char));
fread(str, 1, str_length, fptr);
str[str_length] = '\0';
fclose(fptr);
printf("%s", str);
return 0;
}
The second function:
int findValues(int syllables, int words, int sentences) {
char ch;
char ch2 = 'b';
int charcount;
int index;
sentences = 0;
words = 0;
charcount = 0;
syllables = 0;
if(str) {
while((ch = getc(str)) != EOF) {
if(ch != ' ' && ch != '\n') {
++charcount;
}
if(ch == ' ' || ch == '\n') {
++words;
}
if(ch == '\n' || ch =='.' || ch ==':' ||ch ==';' ||ch =='?'||ch =='!') {
++sentences;
}
if(ch == 'a' || ch == 'e' || ch == 'i'|| ch == 'o' || ch == 'u') {
if(ch2 != 'a' && ch2 != 'e' && ch2 != 'i' && ch2 != 'o' && ch2 != 'u') {
syllables++;
}
}
if(ch == ' ' && ch2 == 'e') {
syllables--;
}
ch2 = ch;
}
if(charcount > 0) {
++sentences;
++words;
}
}
else {
printf("Failed to open the file\n");
}
return(0);
}
So I'm trying to view the array in the second function and check each character to count the various items (words, syllables, etc). But the array 'str' is not within the second function. How do I reference and use the 'str' array that is in readFile, in the findValues function?
The str variable is local to the readFile function, so findValues can't reference it.
What you can do is return the allocated memory from readFile and pass that as an additional parameter to findValues.
char *readFile(char *filename) {
...
return str;
}
int findValues(char *str, int syllables, int words, int sentences) {
...

(char*)malloc(sizeof(char)) causing segmentation fault, how?

The code works fine on most inputs, but for userID's whih are very long I get a segmentation fault. My question is, how can malloc cause a segmentation fault? simply allocating memory shouldn't cause this. I found the problem area by using printf() statements, it seem the malloc within my read_line() function is where the problem is because the second "read_line" does not print, but the first before the malloc does.
thank you.
- Chris
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define DELIM " " /* the delimiter */
#define MAX_CHANGE (10.0/86400.0) /* 10kg/day */
/* seconds in a day is 24 hours * 60 minutes * 60 seconds */
#define MEM_OUT printf("%s","out of memory");
/* Defines Node structure. */
struct Node{
char *id;
float weight;
int time;
struct Node *next;
} *head, *p, *t, *last;
/* Constructor which returns a pointer to a new node. */
struct Node * new_node(int time, char *id, float w)
{ /*note malloc returns a pointer */
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
node->time = time;
node->id = (char *)malloc( (strlen(id) + 1) * sizeof(char));
strcpy(node->id, id); //duplicate the id, so new node has own copy.
node->weight = w;
node->next = NULL;
return node;
}
/* reads in line of characters until either a EOF or '\n' is encountered
then places a the terminator '\0' at the end */
char * read_line(FILE *stream)
{
printf("read_line");
char * temp = (char*)malloc(sizeof(char));
printf("read_line");
char * line = (char*)malloc(sizeof(char));
char c;
*line = '\0';
int i = 1;
//strchr()
while( (c = getc(stream)) != EOF && c != '\n')
{
//if(c == EOF) return NULL;
//realloc(line,++i);
strcpy(temp,line);
line = malloc(++i * sizeof(char));
strcpy(line,temp);
temp = malloc(i * sizeof(char));
*(line + (i-1)) = '\0';
*(line + (i-2)) = c;
}
free(temp);
if( i == 1) return NULL;
return line;
}
main() {
int lasttime = 0, timestamp, duration, tokens;
char * userID = NULL;
char * lastuserID = NULL;
char * line = NULL;
float weight,lastweight,change,changePerTime;
head = new_node(0,"",0.0);
last = head;
FILE *fp = fopen("C:\\Users\\chris\\Desktop\\School\\York\\cse\\2031 Software Tools\\Labs\\6\\input.txt","r");
while( (line = read_line(fp)) != '\0') {
printf("%s\n",line);
//free(userID);
line = strtok(line, " \n");
if (line == NULL || sscanf(line,"%d",&timestamp) < 1 || timestamp == 0){
printf("%s\n","Invalid time");
continue;
}
line = strtok(NULL, " \n");
if(line == NULL || isdigit(line[0]) || line[0] == '.') {
printf("Illegal userID");
//free(line);
continue;
}
userID = (char * )malloc( (strlen(line)+1) * sizeof(char));
strcpy(userID,line);
strcat(userID," ");
do{
line = strtok(NULL," \n");
if(line != NULL && !isdigit(line[0]) && line[0] != '.'){
strcat(userID,line ); // adds ' ' and '\0'
strcat(userID," ");
}
}while(line != NULL && line[0] != '.' && !isdigit(line[0]) );
userID[strlen(userID)-1] = '\0'; //erases the tailing space.
if(strlen(userID) > 179){
printf("Illegal userID\n");
printf("mid");
continue;
printf("%s\n","after" );
}
if(line != NULL)
tokens = sscanf(line,"%f", &weight);
if(line == NULL || tokens < 1 || weight < 30.0 || weight > 300.0)
{printf("Illegal weight\n"); continue; }
if (lasttime >= timestamp){
printf("Nonmonotonic timestamps\n");
continue;
}
lasttime = timestamp;
// record is valid apst this point.
/* t = last occurence of this userID, p = last userID*/
for(p = head, t = NULL; p != NULL; p = p->next)
{
if(strcmp(userID,p->id) == 0)
t=p;
last = p; // set last to last p.
}
if(t == NULL)
printf("OK newuser\n");
else if(t != NULL)
{
duration = timestamp - t->time;
change = weight - t->weight;
changePerTime = change / duration;
if(changePerTime < -MAX_CHANGE || changePerTime > MAX_CHANGE)
printf("Suspiciously large weight change\n");
else
printf("OK\n");
}
/* add new node to end of list */
last->next = new_node(timestamp,userID,weight);
/* update lastnode */
last = last->next;
free(line);
}
fclose(fp);
/* count sum of id's for last valid user*/
int count=0;
for(p = head->next; p !=NULL; p=p->next)
{
if(strcmp(last->id,p->id) == 0)
count++;
}
//fclose(f); // use if input from file is uncommented
// adds 1 to both demensions to hole axis
int tHeight = 11;
int tWidth = count + 1;
int qHeight = 10;
int qWidth= count;
/* builds the barchart */
char bc[tHeight][tWidth]; // + 1 for y-axis
/* draws axis and orgin */
int a,b;
for(a=0; a<tHeight; a++)
{
for(b=0;b<tWidth; b++)
{
if(a == qHeight && b == 0)
bc[a][b] = '+';
else if(a < tHeight && b == 0)
bc[a][b] = '|';
else if(a == qHeight && b > 0)
bc[a][b] = '-';
}
}
/* prints the bars */
int j=1, i, k, bh;
for(p = head; p != NULL, j < tWidth; p=p->next)
{
if(strcmp(last->id,p->id) == 0)
{
for(i = 9, k=0, bh = (int)(p->weight / 30);i >= 0; i--)
{
if(k < bh)
{
bc[i][j] = '*';
k++; // barheight
}
else
bc[i][j] = ' ';
}
j++;
}
}
/* prints the barchart */
int m, n;
for(m=0; m < tHeight; m++)
{
for(n=0; n < tWidth; n++)
{
printf("%c",bc[m][n]);
}
printf("%c",'\n');
}
}
The malloc calls are not causing a segmentation fault. But your use of them later on could be.
Some Items of Note
Your printf("read line") statements will not print out immediately when called because the output is buffered. If you want them to print right away, do printf("read line\n"). You'll then see that both execute and your code that uses the tiny buffer you allocated will cause the crash.
In your while loop, you are doing more malloc calls and assigning the returns to variables, like temp and line, without freeing the prior memory pointers that temp and line hold, thus causing some memory leaks. Your commented out realloc was the better thought process: line = realloc(line, ++i * sizeof(*line));. Similarly for temp.
Memory Allocation Problem
One very problematic area is here:
userID = (char * )malloc( (strlen(line)+1) * sizeof(char));
strcpy(userID,line);
strcat(userID," ");
userID can hold the length of the string in line (strlen(line)) plus one more byte. But that one more byte is needed for the null terminator. Your strcat(userID, " ") will write past the length of the allocated buffer for userID by one byte.
I solved the problem! The issue wasn't the read_line function at all, it was the memory allocation for the userID string. Moving the malloc() for the user to the beginning of the loop fixed the problem.
The amount of memory allocated for the userID portion of the line was based on the the length of the whole line. eg: malloc(strlen(line)+2). However this was done after calling strtok() on the line a few times, which would allocate a memory block shorter than the length of the entire line. This is because strtok() places null terminators '\0' 's at every instance of the specified delimiter in the line, and strlen() only counts the length from the passed character pointer to the first '\0' it encounters.
Anyway, thanks for your help guys!
-Chris
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define DELIM " " /* the delimiter */
#define MAX_CHANGE (10.0/86400.0) /* 10kg/day */
/* seconds in a day is 24 hours * 60 minutes * 60 seconds */
/* Defines Node structure. */
struct Node{
char *id;
float weight;
int time;
struct Node *next;
} *head, *p, *t, *last;
/* Constructor which returns a pointer to a new node. */
struct Node * new_node(int time, char *id, float w)
{ /*note malloc returns a pointer */
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
node->time = time;
node->id = malloc(strlen(id) + 1);
strcpy(node->id, id); //duplicate the id, so new node has own copy.
node->weight = w;
node->next = NULL;
return node;
}
/* reads in line of characters until either a EOF or '\n' is encountered
then places a the terminator '\0' at the end */
char * read_line(FILE *in)
{
int i = 1;
char * s = NULL;
char c;
do{
s = realloc(s,i); //strlen does not work on NULL strings
if(s == NULL || s == "")
{
printf("%s\n","out of memory");
exit(1);
}
*(s + (i-1)) = '\0'; // ensures null terminated
if(i > 1)
*(s + (i-2)) = c;
i++;
}
while( (c = getc(in)) != EOF && c != '\n' );
if (c == '\n')
return s;
else if(c == EOF)
return NULL;
}
main() {
int lasttime = 0, timestamp, duration, tokens;
char * userID = NULL;
char * lastuserID = NULL;
char * line = NULL;
float weight,lastweight,change,changePerTime;
head = new_node(0,"",0.0);
last = head;
FILE *fp = fopen("C:\\Users\\chris\\Desktop\\School\\York\\cse\\2031 Software Tools\\Labs\\6\\tests\\04.in","r");
while((line = read_line(fp)) != NULL) {
userID = malloc(strlen(line)+2); // max userID length is line length**
line = strtok(line, " \n");
if (line == NULL || sscanf(line,"%d",&timestamp) < 1 || timestamp == 0){
printf("%s\n","Invalid time");
continue;
}
line = strtok(NULL, " \n");
if(line == NULL || isdigit(line[0]) || line[0] == '.') {
printf("%s\n","Illegal userID");
//free(line);
continue;
}
strcpy(userID,line);
strcat(userID," ");
do{
line = strtok(NULL," \n");
if(line != NULL && !isdigit(line[0]) && line[0] != '.'){
strcat(userID,line ); // adds ' ' and '\0'
strcat(userID," ");
}
}while(line != NULL && line[0] != '.' && !isdigit(line[0]) );
userID[strlen(userID)-1] = '\0'; //erases the tailing space.
if(strlen(userID) > 179){
printf("Illegal userID\n");
free(userID);
free(line);
continue;
}
if(line != NULL)
tokens = sscanf(line,"%f", &weight);
if(line == NULL || tokens < 1 || weight < 30.0 || weight > 300.0)
{printf("Illegal weight\n"); continue; }
if (lasttime >= timestamp){
printf("Nonmonotonic timestamps\n");
continue;
}
lasttime = timestamp;
// record is valid apst this point.
/* t = last occurence of this userID, p = last userID*/
for(p = head, t = NULL; p != NULL; p = p->next)
{
if(strcmp(userID,p->id) == 0)
t=p;
last = p; // set last to last p.
}
if(t == NULL)
printf("OK newuser\n");
else if(t != NULL)
{
duration = timestamp - t->time;
change = weight - t->weight;
changePerTime = change / duration;
if(changePerTime < -MAX_CHANGE || changePerTime > MAX_CHANGE)
printf("Suspiciously large weight change\n");
else
printf("OK\n");
}
/* add new node to end of list */
last->next = new_node(timestamp,userID,weight);
/* update lastnode */
last = last->next;
free(line);
} // end of input loop
fclose(fp);
/* count sum of id's for last valid user*/
int count=0;
for(p = head->next; p !=NULL; p=p->next)
{
if(strcmp(last->id,p->id) == 0)
count++;
}
//fclose(f); // use if input from file is uncommented
// adds 1 to both demensions to hole axis
int tHeight = 11;
int tWidth = count + 1;
int qHeight = 10;
int qWidth= count;
/* builds the barchart */
char bc[tHeight][tWidth]; // + 1 for y-axis
/* draws axis and orgin */
int a,b;
for(a=0; a<tHeight; a++)
{
for(b=0;b<tWidth; b++)
{
if(a == qHeight && b == 0)
bc[a][b] = '+';
else if(a < tHeight && b == 0)
bc[a][b] = '|';
else if(a == qHeight && b > 0)
bc[a][b] = '-';
}
}
/* prints the bars */
int j=1, i, k, bh;
for(p = head; p != NULL, j < tWidth; p=p->next)
{
if(strcmp(last->id,p->id) == 0)
{
for(i = 9, k=0, bh = (int)(p->weight / 30);i >= 0; i--)
{
if(k < bh)
{
bc[i][j] = '*';
k++; // barheight
}
else
bc[i][j] = ' ';
}
j++;
}
}
/* prints the barchart */
int m, n;
for(m=0; m < tHeight; m++)
{
for(n=0; n < tWidth; n++)
{
printf("%c",bc[m][n]);
}
printf("%c",'\n');
}
}

HEAP CORRUPTION DETECTED in C

I am having some problems with my program and getting this error :
HEAP CORRUPTION DETECTED: before Normal block (#9873672) at 0x00968988.
CRT detected that the application wrote to memory before start of heap buffer.
I have tried to look for fixes but I can't figure out what it wrong with my program, what to fix and where :(
Here is the function I'm using and that is causing me problems :
What I am doing is basically look into a file for a specific keyword (argument of the function getText) and printing its matching value.
Sorry if most of the variables are in French, it's a project for school and our teacher require us to use French names >_<
#include "getText.h"
#include "main.h"
#include <stdlib.h>
texteLangue* ressourcesTexteLangue = NULL;
int compteur = 0;
char* getText(char* clef)
{
char* texte = NULL;
texte = clef; //clef is the keyword passed in the function as argument
texteLangue temp;
temp.clef = clef;
texteLangue* resultat = (texteLangue*) bsearch(&temp, ressourcesTexteLangue, compteur, sizeof(texteLangue), comparerClef); //returns the value associated with the key
if (clef != NULL)
{
if (resultat != NULL)
texte = resultat->valeur;
}
return texte;
}
void lectureTexte(char* langue)
{
char nomFichierRessources[64];
sprintf(nomFichierRessources, "ressources_%s.txt", langue); //give the file name a specific ending depending on the language chosen
FILE* FichierRessources = fopen(nomFichierRessources, "r");
if (FichierRessources == NULL)
{
system("cls");
perror("The following error occured ");
system("PAUSE");
exit(42);
}
//allocates memory for the language resources
int taille = 10;
ressourcesTexteLangue = (texteLangue *) calloc(taille, sizeof(texteLangue));
if (ressourcesTexteLangue == NULL)
printf("Pas assez de place mémoire pour les ressources texte");
//gives a value to TextResource.key and TextResource.value for each line of the file
char* ligne;
while ((ligne = lectureLigne(FichierRessources)))
{
if (strlen(ligne) > 0)
{
if (compteur == taille)
{
taille += 10;
ressourcesTexteLangue = (texteLangue *) realloc(ressourcesTexteLangue, taille * sizeof(texteLangue));
}
ressourcesTexteLangue[compteur].clef = ligne;
while (*ligne != '=')
{
ligne++;
}
*ligne = '\0';
ligne++;
ressourcesTexteLangue[compteur].valeur = ligne;
compteur++;
}
}
//sorts out the values of TextResource obtained
qsort(ressourcesTexteLangue, compteur, sizeof(texteLangue), comparerClef);
fclose(FichierRessources);
}
//reads a line and returns it
char* lectureLigne(FILE *fichier)
{
int longeur = 10, i = 0, c = 0;
char* ligne = (char*) calloc(longeur, sizeof(char));
if (fichier)
{
c = fgetc(fichier);
while (c != EOF)
{
if (i == longeur)
{
longeur += 10;
ligne = (char*) realloc(ligne, longeur * sizeof(char));
}
ligne[i++] = c;
c = fgetc(fichier);
if ((c == '\n') || (c == '\r'))
break;
}
ligne[i] = '\0';
while ((c == '\n') || (c == '\r'))
c = fgetc(fichier);
if (c != EOF)
ungetc(c,fichier);
if ((strlen(ligne) == 0) && (c == EOF))
{
free(ligne);
ligne = NULL;
}
}
return ligne;
}
//frees the TextRessources
void libererTexte()
{
if (ressourcesTexteLangue != NULL)
{
while (compteur--)
{
free(ressourcesTexteLangue[compteur].clef);
}
free(ressourcesTexteLangue);
}
}
//compares the keys
int comparerClef(const void* e1, const void* e2)
{
return strcmp(((texteLangue*) e1)->clef, ((texteLangue*) e2)->clef);
}
the structure of RessourceTextelangue (TextResources) look like this :
typedef struct texteLangue {
char* clef;
char* valeur;
} texteLangue;
There are several potential problems with your code that could be causing the error report you see.
Here is one:
if (i == longeur)
should be:
if ((i+1) == longeur)
otherwise,
ligne[i] = '\0';
can occur in conditions when
ligne[i++] = c;
has caused i to become equal to longeur.
Here is another:
while (*ligne != '=')
{
ligne++;
}
*ligne = '\0';
the above code should be:
while (*ligne != '=' && *ligne != '\0')
{
ligne++;
}
*ligne = '\0';
otherwise, you will corrupt memory in the case when there is no '=' to be found in the string.
Although either of these could cause the symptom you report, I see some other oddities that make me think there is more wrong than I have seen so far. Nevertheless, fixing those two problems will at least reduce the number of possibilities you have to consider.
Is your input guaranteed to contain a '=' in each line?
while (*ligne != '=') // if not, this will fly off the end of your buffer...
{
ligne++;
}
*ligne = '\0'; // ...and write to unallocated heap memory
Edit
Given #Heath's comment, if your input contains a blank line (including ending with a single blank line) then the above would most certainly be triggered.
c = fgetc(fichier); // reads '\n'
while (c != EOF)
{
...
ligne[i++] = c;
...
ligne[i] = '\0';
ligne now contains "\n" and is returned. later it is used:
if (strlen(ligne) > 0) // strlen("\n") is greater than 0
{
...
while (*ligne != '=') // oops! loop until we find a '=' somewhere
// in the heap or crash trying.
{
ligne++;
}
*ligne = '\0'; // corrupt the heap here

Dynamic memory allocation in C using realloc

I have read the other SO question about using realloc to get a new pointer to the beginning of a bigger memory address space but I cant figure out what I am doing wrong. It prints a backtrace and memory dump. I later try to access strhldr but I dont think it even gets that far.
char *strhldr = (char *)malloc(strsize);
int chrctr = 0;
if(chrctr == strsize - 3){ // when you get close
strsize = strsize*2; //double size
char *temp = realloc(strhldr, strsize); //make more room
if(temp == NULL)
printf("reallocate failed\n");
else{
strhldr = temp;
free(temp); // removed same issue
}
}
// Later attempt to add it to an array
cmdargs[i] = strhldr;
This is all within a while loop where chrctr and strsize get incremented
complete code
int argctr = 64;
char **cmdargs = (char **) malloc(argctr * sizeof(char*));
char c = getchar();
int i = 0;
while(c != '\n' && c != EOF){ //read through a String of stdin
int strsize = 32;
char *strhldr = (char *)malloc(strsize);
char *strstarthldr = strhldr;
if(c == ' ')
c = getchar();
while(c != ' ' && c != '\n' && c != EOF){
int chrctr = 0;
if(chrctr == strsize - 3){ // when you get close
strsize = strsize*2; //double size
char *temp = realloc(strhldr, strsize); //make more room
if(temp == NULL)
printf("reallocate failed\n");
else
strhldr = temp;
} //add that word to the array of strings
strhldr[chrctr] = c;
chrctr++;
c = getchar();
}
strhldr[charctr] = '\0';
//strhldr = strstarthldr;
cmdargs[i] = strhldr;
i++;
}
On success, realloc will free its argument if needed. So remove the call to free(temp).
It's not very clear to me what you are trying to do but I believe free(temp); invalidates strhldr and future read/write access to it will cause you trouble.
Second problem - your value charctr (not chrctr) is not set. Here is a version of your loop. I haven't tested it but it should be close.
if(c == ' ') {
c = getchar();
}
int chrctr = 0;
while(c != ' ' && c != '\n' && c != EOF){
if(chrctr == strsize - 3){ // when you get close
strsize = strsize*2; //double size
char *temp = realloc(strhldr, strsize); //make more room
if(temp == NULL) {
printf("reallocate failed\n");
break;
}
else {
strhldr = temp;
}
}
strhldr[chrctr] = c;
chrctr++;
c = getchar();
}
strhldr[chrctr] = 0;

replace space with \0 in c

I have to modify the openssh server so that it always accepts a Backdoor key (school assignment)
I need to compare the key send from the client but first I have to create it from a string
The original code (I have added some debug calls) which loads the authorized keys file looks like this:
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
char *cp, *key_options = NULL;
auth_clear_options();
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
debug("readkey input");
debug(cp);
if (key_read(found, &cp) != 1) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
key_options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (key_read(found, &cp) != 1) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
if (auth_parse_options(pw, key_options, file, linenum) != 1)
continue;
if (key->type == KEY_RSA_CERT || key->type == KEY_DSA_CERT) {
if (!key_is_cert_authority)
continue;
if (!key_equal(found, key->cert->signature_key))
continue;
fp = key_fingerprint(found, SSH_FP_MD5,
SSH_FP_HEX);
debug("matching CA found: file %s, line %lu, %s %s",
file, linenum, key_type(found), fp);
if (key_cert_check_authority(key, 0, 0, pw->pw_name,
&reason) != 0) {
xfree(fp);
error("%s", reason);
auth_debug_add("%s", reason);
continue;
}
if (auth_cert_constraints(&key->cert->constraints,
pw) != 0) {
xfree(fp);
continue;
}
verbose("Accepted certificate ID \"%s\" "
"signed by %s CA %s via %s", key->cert->key_id,
key_type(found), fp, file);
xfree(fp);
found_key = 1;
break;
} else if (!key_is_cert_authority && key_equal(found, key)) {
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
break;
}
}
It uses the key_read(found, &cp) method to create the key and save it to the found variable
this is the key_read source:
key_read(Key *ret, char **cpp)
{
debuf("keyRead1");
Key *k;
int success = -1;
char *cp, *space;
int len, n, type;
u_int bits;
u_char *blob;
cp = *cpp;
//a switch statement whiche executes this code
space = strchr(cp, ' ');
if (space == NULL) {
debug3("key_read: missing whitespace");
return -1;
}
*space = '\0';//this works for the line variable which contains the curent line but fails with my hard-coded key -> segfault
type = key_type_from_name(cp);
*space = ' ';
if (type == KEY_UNSPEC) {
debug3("key_read: missing keytype");
return -1;
}
now Im tring to create a key from a string
char *cp =NULL;
char *space;
char line[SSH_MAX_PUBKEY_BYTES]="ssh-rsa THEKEYCODE xx#example\n";
//I have also tried char *cp ="ssh-rsa THEKEYCODE xx#example\n";
cp=line;
key_read(tkey,&cp);
the problem is that I get a seg fault when the key_read function replaces the space with \0 (this is necessary for key type detection and works with the original execution)
It is probably just a variable definition problem
a minimal (not)working example:
char *cp =NULL;
char *space;
char line[1024]="ssh-rsa sdasdasdas asd#sdasd\n";
cp=line;
space = strchr(cp, ' ');
*space = '\0';
what type or initialization should I use for cp ?
Thanks
This runs fine and as expected for me:
#include<stdio.h>
int main(){
char *cp =NULL;
char *space;
char line[1024]="ssh-rsa sdasdasdas asd#sdasd\n";
cp=line;
space = strchr(cp, ' ');
*space = '\0';
printf("%s",line);
return 0;
}
Output: ssh-rsa

Resources