473,804 Members | 2,139 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Your opinions on some code, please

In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValu e, elem->value);
while( tempValue[0] == '0' )
{
tempValue++;
}
some_api_funtio n(tempValue); /* Alt */
}

(The comments are mine and denote lines that have been altered
for brevity or clarity)

I wonder if the denizens of comp.lang.c would care to comment?

Emmet.

Nov 14 '05 #1
7 1261

"Emmet Caulfield" <em***@netrogen .com> schreef in bericht
news:11******** **************@ c13g2000cwb.goo glegroups.com.. .
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValu e, elem->value);
while( tempValue[0] == '0' )
{
tempValue++;
}
some_api_funtio n(tempValue); /* Alt */
}

(The comments are mine and denote lines that have been altered
for brevity or clarity)

I wonder if the denizens of comp.lang.c would care to comment?


not checking the return value of malloc.
not checking for buffer overflow in strcpy
tempValue not freed (I can't believe such easy to avoid mem leaks are
written)
Nov 14 '05 #2
Emmet Caulfield <em***@netrogen .com> wrote:
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert: if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
Missing check for return value of malloc(). Using magic numbers is
bad style.
strcpy(tempValu e, elem->value);
Potential buffer overrun when the string in elem->value (lets hope
it's one...) is longer than 31 chars. Hopefully it's checked some-
where else that this condition is always satisfied.
while( tempValue[0] == '0' )
{
tempValue++;
}
This looks really stupid since afterwards it's difficult to determine
what tempValue originally was to be able to call free() on it - since
the skipped '0' chars are also in elem->value (lets hope it won't get
changed somewhere before that) it should be possible to get back at the
original value of tempValue but why not store it somewhere safely? I
also would prefer to write the 'tempValue[0]' as '*tempValue'.
some_api_funtio n(tempValue); /* Alt */
Lets just hope in that function nothing gets appended to the
tempValue buffer because that can't be done safely...

And now we are missing a free() on tempValue (after carefully
correcting it to have the value of what was returned by malloc()).
A perfect specimen of a memory leak. The only way around that would
be when tempValue gets free()ed in some_api_funtio n() (but to do
that safely requires that the function knows about the elem->value
string). But that would be extremely bad style for several reasons.
}

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@p hysik.fu-berlin.de
\______________ ____________ http://www.toerring.de
Nov 14 '05 #3
"Emmet Caulfield" <em***@netrogen .com> wrote:
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
And if malloc() fails, you scribble through the null pointer.
The magic number 32 is also hardly advisable.
strcpy(tempValu e, elem->value);
This may look like a mistake, but it's quite possible that
SOME_MANIFEST_C ONSTANT means that there will never be more than 32 (or
more solidly, SOME_MANIFEST_S IZE) chars in elem->value, and that this
has been checked in the surrounding code. If not:

*tempValue='\0' ;
strncat(tempVal ue, elem->value, SOME_MANIFEST_S IZE-1);
while( tempValue[0] == '0' )
{
tempValue++;
}
some_api_funtio n(tempValue); /* Alt */
And you lose the original pointer that malloc() returned, so you cannot
free() it. Even if some_api_functi on puts tempValue into a global
container (tree, list, whatever), you have no way of knowing whether it
is the original pointer or one a few characters further on, so you can't
pass it to free(). Result: memory leak.
}


Tell me, which inadvisable product's code did you find this in?

Richard
Nov 14 '05 #4
"Emmet Caulfield" <em***@netrogen .com> wrote in message
news:11******** **************@ c13g2000cwb.goo glegroups.com.. .
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValu e, elem->value);
while( tempValue[0] == '0' )
{
tempValue++;
}
some_api_funtio n(tempValue); /* Alt */
}

(The comments are mine and denote lines that have been altered
for brevity or clarity)

I wonder if the denizens of comp.lang.c would care to comment?


Unchecked return from malloc().
Small, fixed-size malloc() is generally pointless - might as well just use
an auto buffer.
Potential strcpy() buffer overflow.
tempValue cannot be free()d, because the while loop changes the value in a
non-reversible way.
Copies the whole thing then skips any leading '0' characters - could skip
them first and copy only the remainder.
If some_api_functi on() doesn't modify the pointed-to buffer then there's no
need to copy at all.
I won't bother with the style/layout issues because, aside from being
religious, they are minor by comparison.

If some_api_functi on() modifies the buffer, I'd probably use:

if (elem->tag == SOME_MANIFEST_C ONSTANT) {
const char *p;
char *temp;

for (p = elem->value; *p == '0'; ++p)
;
temp = malloc(strlen(p ) + 1);
if (!temp) abort(); /* or something more appropriate */
strcpy(temp, p);
some_api_functi on(temp);
free(temp);
}

If not:

if (elem->tag == SOME_MANIFEST_C ONSTANT) {
const char *p;
for (p = elem->value; *p == '0'; ++p)
;
some_api_functi on(p);
}

Or (since you mention the code is duplicated except for the if test) put the
body of the if into a seperate function, wrapping the call to
some_api_functi on(), or (if the buffer is not modified) use a function which
returns a pointer to the first non-'0' character. Or (if appropriate) use
"if (elem->tag == x || elem->tag == y) ..."

Alex
Nov 14 '05 #5


Emmet Caulfield wrote:
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValu e, elem->value);
- there is no test to check whether malloc() succeeded
- 32 is a magic number which sooner or later _will_ break the code;
use the same symbolic constant used for obtaining the storage
for elem->value or, if elem->value is a string (as indicated by
the use of strcpy()), malloc(strlen(e lem->value) + 1)
- only with large enough buffer pointed to by tempValue,
we can be sure that there is no risk of buffer overrun by
calling strcpy() (using strlen(elem->value) + 1 guarantees
that).
strcpy() and even the safer variant strncpy() are slightly flawed
and have to be handled with care. If this part is not time critical
and you have a standard library which already has snprintf() (a C99
standard library function), you may consider using this instead and
just check the return value.
while( tempValue[0] == '0' )
{
tempValue++;
}
some_api_funtio n(tempValue); /* Alt */
free(tempValue) ;
Otherwise you have a memory leak. }

(The comments are mine and denote lines that have been altered
for brevity or clarity)

I wonder if the denizens of comp.lang.c would care to comment?


Ask your '"C" expert' whether he really considers the original
version good code. If he does, then there goes the expert rank.
If he does not and this is a crappy module whipped up in short
time to meet some deadlines, you should reconsider your software
production process.
Cheers
Michael
--
E-Mail: Mine is a gmx dot de address.

Nov 14 '05 #6
In article <11************ **********@c13g 2000cwb.googleg roups.com>
Emmet Caulfield <em***@netrogen .com> wrote:
In the course of examining the code for an Internet-connected
authenticati on server, I came across the following code ...

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValu e, elem->value);
while( tempValue[0] == '0' )
{
tempValue++;
}
some_api_funtio n(tempValue); /* Alt */
}


As others have said, it is certainly peculiar code. Without
knowing anything more about it, I would probably have written
something more along these lines:

if (elem->tag == SOME_MANIFEST_C ONSTANT) {
/*
* Find the part beginning with a '0' character, which
* is guaranteed to exist, then duplicate that and the
* remainder of the string to give room for the api_zog()
* function to modify.
*
* This comment would make much more sense if we had any
* idea *why* we are finding the first '0' character and
* copying the remainder.
*/
char *p = strchr(elem->value, '0');

if (p == NULL)
panic("gronkelf latz(): elem->value (%s) missing required '0'",
elem->value);
p = xstrdup(p); /* malloc+strcpy, with panic if NULL */
api_zog(p);
free(p);
}
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #7
Emmet Caulfield wrote:
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValu e, elem->value);
What makes you so sure 32 characters is enough to hold the length of
elem->value? Usually, in place of explicit constants such as "32" you
use a #define which makes your meaning clear, such as MAX_VALUE_LEN,
which you then use in place of 32 above, and semantically as required
in other places in your code.

As others have pointed out, malloc can return with NULL, so technically
you should handle that case.
while( tempValue[0] == '0' )
{
tempValue++;
}
It appears as though what you are trying to do here is to skip a '0'
(possibly repeated) prefix the value of your string. But what if the
string contents itself is nothing but '0's? Is it really your
intention to strip them all away? Assuming that you were trying to
text encode a numeric value of some kind, the number "0" would be
reduced to the empty string here.
some_api_functi on(tempValue); /* Alt */
}


Ok, as others have pointed out you have a memory leak here, because you
forgot to use free() on what was given to you from malloc. You cannot
simply put free(tempValue) before the } because you've *lost* the
original pointer due to your destructive operation of incrementing it,
as a means of trying to "get rid of leading 0s". This may not be a big
deal if you are using something called the Boehm garbage collector
tool, however, you did not make this clear.

Let's try for a rewrite:

if( elem->tag == SOME_MANIFEST_C ONSTANT ) /* Alt */
{
char *s, *t = elem->value;
int len;

while (t[0] == '0' && t[1] !='\0') t++;
len = strlen (t) + 1;
s = malloc (len * sizeof (char));
if (s) {
memcpy (s, t, len);
some_api_functi on (s);
free (s); /* Unless the function above frees it */
} else {
/* Do something about the failure of malloc */
}
}

So what we've done is we've scanned for the prefixed '0's in the
original string before its copied, as we are allowing for a single "0"
digit without truncating it down to "". Then we've allocated exactly
as much space as it required by the string we are copying. We've
checked for a possible failure of malloc. And finally we free the
memory for the copied string ourself (or we could remove that free()
line and require that the function "some_api_funct ion" do the freeing,
or some other mechanism such as the Boehm garbage collector.)

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Nov 14 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
3230
by: jerrygarciuh | last post by:
Hi all, I was just wondering what popular opinion is on PHP giving this warning: Warning: Invalid argument supplied for foreach() in /home/boogerpic/public_html/my.php on line 6 when presented with an indefined variable. It makes sense to me to warn if an unacceptably defined var is passed but it
4
1294
by: xeys_00 | last post by:
Well, I'm auditing CS164 again. C++ part 1, basically. I'd like to know if I can submit some code to the group and get some opinions, as the instructor is not going to do anything more than let me sit in on lectures. I don't have access to the labs, or anything she's got going on, so I am going to try to go to the classes and come up with my own ideas of what to code. The first project is a program that takes 10 names, and 3 grades for...
3
2140
by: Jack Klein | last post by:
I'm looking for opinions on a C technique I, and others, have used successfully in the past. While some people swear by, apparently others swear at it. Assume a part of a program too large to fit comfortably in a single source file, call it a "module". Let's call it "module A". Also assume for various reasons module A needs a private data store with static storage duration, accessible from files in more than one translation unit. ...
192
9533
by: Vortex Soft | last post by:
http://www.junglecreatures.com/ Try it and tell me what's happenning in the Microsoft Corporation. Notes: VB, C# are CLS compliant
3
1368
by: CDMAPoster | last post by:
A.K.A. Is Double Dating a bad thing :-)? My post from several hours ago may have gotten lost so please forgive me if something similar to this shows up twice. From a modular programming class I took many years ago I was taught that it is important to maintain a good interface to hidden code so that when updates are created they can be tested and swapped into place without the program having to know the details of the hidden code. The...
33
4697
by: genc_ymeri | last post by:
Hi over there, Propably this subject is discussed over and over several times. I did google it too but I was a little bit surprised what I read on internet when it comes 'when to use what'. Most of articles I read from different experts and programmers tell me that their "gut feelings" for using stringBuilder instead of string concatenation is when the number of string concatunation is more then N ( N varies between 3 to max 15 from...
13
2440
by: Miro | last post by:
Ok I have been slowely - and ever so slowely teaching myself VB.net Currently I have created an MDB file by code, and added fields to the MDB file by code. I like this solution because, ( im assuming ) if I create an EXE and I load an MDB file, I can see if certain fields are there, and if not add them. Kinda like an Update that is imbeded into the EXE, so you dont always have to create an Install shield.
112
4773
by: Prisoner at War | last post by:
Friends, your opinions and advice, please: I have a very simple JavaScript image-swap which works on my end but when uploaded to my host at http://buildit.sitesell.com/sunnyside.html does not work. To rule out all possible factors, I made up a dummy page for an index.html to upload, along the lines of <html><head><title></title></ head><body></body></html>.; the image-swap itself is your basic <img src="blah.png"...
21
2673
by: Steve Swift | last post by:
On page 90 of my O'Reilly "Javascript The definitive guide" 3rd edition there is an example of an If/Else construct: (some text removed) If (username != null) alert("Hello " + username); else { username = prompt("What is your name?"); alert("Hello " + username); }
0
9714
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
1
10351
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10096
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7638
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6866
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5534
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4311
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3834
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3002
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.