Question related to string functions

S

somenath

Hi All,

I was going through one piece of code which is written by an
experience programmer and it is working fine.
But I think the use of "strstr" is not proper because it may show
undefined behavior.



char *returnValueFromIniFile(char *iniFilePath,char *keyIntheFile)
{
FILE *FD_IniFileP =NULL;
char key[SIZE_OF_ARRAY]={'0'};
static char value[SIZE_OF_ARRAY]={'\0'};
FD_IniFileP = fopen(iniFilePath,"r");
if( FD_IniFileP != NULL )
{
/* File Open Success*/
while (fscanf(FD_IniFileP,"%s",key)!= EOF)
{
if(strstr(key,keyIntheFile)!=NULL)
{


/*Make sure key contains "="*/
if(strstr(key,"=")!=NULL)
{
/*Sepereate the key and the value */
char *positionOfequal = strstr(key,"="); /* as "="
is not terminated by '\0' it can show undefined behavior ? */

/*increment the positionOfequal to reach the
beganing of the value */
positionOfequal +=1;
assert(strlen(positionOfequal)<SIZE_OF_ARRAY);
strcpy(value,positionOfequal);
break;
}

}/* End of if(strstr(key,keyIntheFile)!=NULL)*/
memset(key,'\0',SIZE_OF_ARRAY);

}/* End of while (fscanf(FD_IniFileP,"%s",key)!= EOF)*/

}/* End of if( FD_IniFileP != NULL )*/
if (FD_IniFileP)
{
fclose(FD_IniFileP);
}

return value;

}

I think the statement "char *positionOfequal = strstr(key,"=");" can
show undefined behavior .
1) Is my understanding correct ?
I have another question
2) Can we pass directly sequence of characters to the function which
expects string ?
For example strcpy(dest,"some");
Strcat(dest,"abc"); ?
Regards,
Somenath
 
R

Richard Heathfield

somenath said:
Hi All,

I was going through one piece of code which is written by an
experience programmer and it is working fine.

It fails to protect its key buffer against overruns, so I can't agree
that it's working fine.
But I think the use of "strstr" is not proper because it may show
undefined behavior.

if(strstr(key,keyIntheFile)!=NULL)
{


/*Make sure key contains "="*/
if(strstr(key,"=")!=NULL)
{
/*Sepereate the key and the value */
char *positionOfequal = strstr(key,"=");

Calling strstr twice here seems to be a little unnecessary. Still, it's
not actually wrong. Incidentally, strchr would have been adequate.

/* as "="
is not terminated by '\0' it can show undefined behavior ? */

"=" is a string literal, which *IS* terminated by a null character.

2) Can we pass directly sequence of characters to the function which
expects string ?
For example strcpy(dest,"some");
Strcat(dest,"abc"); ?

Yes, you can pass string literals to standard library functions when you
are matching parameters that take const char * (as in your strcpy
example). I can't answer for your Strcat example, since I've never
heard of a Strcat function. If you meant strcat, then yes, that, too,
can legitimately take a string literal as the second argument.
 
S

somenath

somenath said:



It fails to protect its key buffer against overruns, so I can't agree
that it's working fine.

Many thanks for the response.

If i have propely understood you are indicating that " while
(fscanf(FD_IniFileP,"%s",key)!= EOF) "
can cause problem . is it so ?
if it is then if I change the code as following will it solve the
problem ?
#define str(x) # x
#define xstr(x) str(x)


char *returnValueFromIniFile(char *iniFilePath,char *keyIntheFile)
{
FILE *FD_IniFileP =NULL;
char key[SIZE_OF_ARRAY+1]={'0'};
static char value[1]={'\0'};
FD_IniFileP = fopen(iniFilePath,"r");
if( FD_IniFileP != NULL )
{
/* File Open Success*/
//cout<<"\n Opening of INI file Succeeded \n "<<endl;
while (fscanf(FD_IniFileP,"%" xstr(SIZE_OF_ARRAY) "[^
\n]" ,key)!= EOF)
{


Calling strstr twice here seems to be a little unnecessary. Still, it's
not actually wrong. Incidentally, strchr would have been adequate.

/* as "="


"=" is a string literal, which *IS* terminated by a null character.



Yes, you can pass string literals to standard library functions when you
are matching parameters that take const char * (as in your strcpy
example). I can't answer for your Strcat example, since I've never
heard of a Strcat function. If you meant strcat,

Sorry it is my typing mistake. It would be strcat.
 
S

somenath

somenath said:



It fails to protect its key buffer against overruns, so I can't agree
that it's working fine.


Calling strstr twice here seems to be a little unnecessary. Still, it's
not actually wrong. Incidentally, strchr would have been adequate.

/* as "="


"=" is a string literal, which *IS* terminated by a null character.



Yes, you can pass string literals to standard library functions when you
are matching parameters that take const char * (as in your strcpy
example). I can't answer for your Strcat example, since I've never
heard of a Strcat function. If you meant strcat, then yes, that, too,
can legitimately take a string literal as the second argument.
I have one doubt here.
Suppose
#define TEMP_STR "xyz"
can i use string related function such as strcpy(dest,TEMP_STR); ?
 
R

Richard Heathfield

somenath said:
Yes, you can pass string literals to standard library functions when
you are matching parameters that take const char * (as in your strcpy
example). [...]
I have one doubt here.
Suppose
#define TEMP_STR "xyz"
can i use string related function such as strcpy(dest,TEMP_STR); ?

Yes, because it's just a different way of writing strcpy(dest,"xyz");

But TEMP_STR is a bad name for a string literal. String literals exist
for the entire lifetime of the program, so they are hardly temporary!
 
K

Keith Thompson

somenath said:
I was going through one piece of code which is written by an
experience programmer and it is working fine.
But I think the use of "strstr" is not proper because it may show
undefined behavior. [...]
/*Sepereate the key and the value */
char *positionOfequal = strstr(key,"="); /* as "="
is not terminated by '\0' it can show undefined behavior ? */ [...]
I think the statement "char *positionOfequal = strstr(key,"=");" can
show undefined behavior .
1) Is my understanding correct ?
I have another question
2) Can we pass directly sequence of characters to the function which
expects string ?
For example strcpy(dest,"some");
Strcat(dest,"abc"); ?

A string literal is (almost) always implicitly terminated by a '\0'
character. The literal "=" specifies the two-character sequence
'=', '\0'.

(The only exception is when a string literal is used to initialize an
array whose size is specified as exactly the length of the array, such
as
char s[3] = "abc";
but this is a very unusual case, and should be avoided; instead, you
can use
char s[] = "abc";
to get a properly zero-terminated string.)
 
R

Richard Heathfield

Keith Thompson said:
somenath said:
I was going through one piece of code which is written by an
experience programmer and it is working fine.
But I think the use of "strstr" is not proper because it may show
undefined behavior. [...]
/*Sepereate the key and the value */
char *positionOfequal = strstr(key,"="); /* as
"="
is not terminated by '\0' it can show undefined behavior ? */ [...]
I think the statement "char *positionOfequal = strstr(key,"=");" can
show undefined behavior .
1) Is my understanding correct ?
I have another question
2) Can we pass directly sequence of characters to the function which
expects string ?
For example strcpy(dest,"some");
Strcat(dest,"abc"); ?

A string literal is (almost) always implicitly terminated by a '\0'
character. The literal "=" specifies the two-character sequence
'=', '\0'.

(The only exception is when a string literal is used to initialize an
array whose size is specified as exactly the length of the array, such
as
char s[3] = "abc";

What makes you think this is an exception?

The Standard says:

"A character string literal has static storage duration and type "array
of char," and is initialized with the given characters. A wide string
literal has static storage duration and type "array of wchar_t," and is
initialized with the wide characters corresponding to the given
multibyte characters. Character string literals that are adjacent
tokens are concatenated into a single character string literal. A null
character is then appended."

No exceptions.

I know what you're thinking of, but that's a special case of
initialisation, not a special case of string literals.

but this is a very unusual case, and should be avoided;

....by newbies, at any rate. There are (rare) times when it's Exactly
What's Needed.

<snip>
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said: [...]
A string literal is (almost) always implicitly terminated by a '\0'
character. The literal "=" specifies the two-character sequence
'=', '\0'.

(The only exception is when a string literal is used to initialize an
array whose size is specified as exactly the length of the array, such
as
char s[3] = "abc";

What makes you think this is an exception?

The Standard says:

"A character string literal has static storage duration and type "array
of char," and is initialized with the given characters. A wide string
literal has static storage duration and type "array of wchar_t," and is
initialized with the wide characters corresponding to the given
multibyte characters. Character string literals that are adjacent
tokens are concatenated into a single character string literal. A null
character is then appended."

No exceptions.

I know what you're thinking of, but that's a special case of
initialisation, not a special case of string literals.

What are you, some kind of pedant?

:cool:}

Yeah, you're right. C99 6.7.8p14 says:

An array of character type may be initialized by a character
string literal, optionally enclosed in braces. Successive
characters of the character string literal (including the
terminating null character if there is room or if the array is of
unknown size) initialize the elements of the array.
...by newbies, at any rate. There are (rare) times when it's Exactly
What's Needed.

Hmm. I meant to qualify that somehow, and I thought I had.
 
B

Bart van Ingen Schenau

somenath said:
somenath said:



It fails to protect its key buffer against overruns, so I can't agree
that it's working fine.

Many thanks for the response.

If i have propely understood you are indicating that " while
(fscanf(FD_IniFileP,"%s",key)!= EOF) "
can cause problem . is it so ?
if it is then if I change the code as following will it solve the
problem ?
#define str(x) # x
#define xstr(x) str(x)


char *returnValueFromIniFile(char *iniFilePath,char *keyIntheFile)
{
FILE *FD_IniFileP =NULL;
char key[SIZE_OF_ARRAY+1]={'0'};
static char value[1]={'\0'};
FD_IniFileP = fopen(iniFilePath,"r");
if( FD_IniFileP != NULL )
{
/* File Open Success*/
//cout<<"\n Opening of INI file Succeeded \n "<<endl;
while (fscanf(FD_IniFileP,"%" xstr(SIZE_OF_ARRAY) "[^
\n]" ,key)!= EOF)
{

Yes, that will properly protect you from a buffer overrun of the key
array.
But your change also changes the semantics of the program.
The original line:
 while (fscanf(FD_IniFileP,"%s",key)!= EOF)
would stop reading on the first whitespace character, but your rewrite
only stops at the end of a line.
To preserve the original semantics, you should use
while (fscanf(FD_IniFileP,"%" xstr(SIZE_OF_ARRAY) "s" ,key)!= EOF)

Bart v Ingen Schenau
 
M

Malcolm McLean

Keith Thompson said:
Richard Heathfield said:
I know what you're thinking of, but that's a special case of
initialisation, [ unterminated char arrays] not a special case of
string literals.

What are you, some kind of pedant?
If we can't be literal about literals, where is it appropriate?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top