Plz explain me the following code

T

Tom St Denis

Tom St Denis wrote:

) Safe being a relative term I suppose...  Generally as part of safe
) development practices I just avoid it and always use strncpy with
) proper limits (and/or I enforce the length of the source by reporting
) errors if it's too long).

Are you kidding ?  strncpy is less safe than strcpy, not to mention slower.
It was never meant to be 'strcpy-with-limits'.

They should put something like BSD's strlcpy in the standard, that would
actually be useful.

Since this debate happens every 6 days in clc I won't really argue one
way or the other.

My point is it's part of *a* secure development process. It's not the
only way. You could just as easily enforce length checks then use
memcpy for all it matters. Provided you're consistent and thorough.

Tom
 
W

Willem

Tom St Denis wrote:
)> Tom St Denis wrote:
)>
)> ) Safe being a relative term I suppose...  Generally as part of safe
)> ) development practices I just avoid it and always use strncpy with
)> ) proper limits (and/or I enforce the length of the source by reporting
)> ) errors if it's too long).
)>
)> Are you kidding ?  strncpy is less safe than strcpy, not to mention slower.
)> It was never meant to be 'strcpy-with-limits'.
)>
)> They should put something like BSD's strlcpy in the standard, that would
)> actually be useful.
)
) Since this debate happens every 6 days in clc I won't really argue one
) way or the other.

You're right about that.

) My point is it's part of *a* secure development process. It's not the
) only way. You could just as easily enforce length checks then use
) memcpy for all it matters. Provided you're consistent and thorough.

Point taken.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
N

Nick Keighley

If you're a C developer of any sort and are just learning about
undefined behaviour you need to put away your C compiler and read the
standard from start to finish.  Really that's kinda bad.

I think you need to get out more. I suspect 90% or more of
C programmers haven't a clue what "undefined behaviour" means.

Which is why people say things like "this program is supposed
to exhibit undefined behaviour but when I ran it worked ok"

When i was first learning C I kept a note of the compiler bugs that
another programmer encountered. Most of (possibly all of them) turned
out to be well-I-expected-it-to-do-this (guessed in other words)
or undefined behaviour. Sadly I no longer have the list.

I have a hard copy of the standard. My K&R goes walk-about but my
copy of the standard never does.
 
W

Willem

Nick Keighley wrote:
) I think you need to get out more. I suspect 90% or more of
) C programmers haven't a clue what "undefined behaviour" means.

Same goes for any other language that has 'undefined behaviour'.
Perl, SQL, to name but a few.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
P

Processor-Dev1l

He's correct. You don't know what a memory leak is. A memory leak is
when a program allocates memory using malloc(), calloc(), or realloc(),
and fails to free it; some people would restrict the term "leak" to
those cases where the failure to free the memory was unintentional.

Memory leaks are mostly innocuous, except insofar as they make it more
likely that some future call to malloc(), calloc() or realloc() will fail..

I'm not sure there's any single standard term for what you describe, but
the consequence of what you're talking about can be referred to as
memory corruption.
Ok, memory corruption, I will write it somewhere down and use it next
time on similar topic :)
On systems without adequate memory protection, memory corruption could,
in principle, cause your program to do just about anything the operating
system has given it permission to do. Depending upon what those
permissions are, and depending upon what hardware that computer is
connected to, it might be able to do things MUCH worse than changing
data on the hard drive. Imagine the possibilities if, for instance, a
computer is able to control, directly or indirectly, a weapons system, a
nuclear power plant, the navigation system of an airplane, or (for
security reasons) a self-destruct mechanism, and your program has
permission to exercise that control.
Well, one of my teacher said that virus running on the lowest possible
level could bypass even operating system restrictions with no problem
and do anything.
 
T

Tom St Denis

I think you need to get out more. I suspect 90% or more of
C programmers haven't a clue what "undefined behaviour" means.

Which is why people say things like "this program is supposed
to exhibit undefined behaviour but when I ran it worked ok"

The problem really is that there a lot of people with arbitrary levels
of training and experience who call themselves developers. To be a
professional developer you basically have to show some modicum of
understanding of the syntax. I've seen quite a few developers who do
any number of classic development mistakes

- putting all your code in one large function
- putting more than one exported function in a .c file
- putting all your .c files in the same directory
- not using a proper make system
- not indenting to any rational standard or consistency
- initializing variables where you declare them
- tolerating obvious compiler warnings [like uninitialized variables,
undefined functions, etc]
- not checking return values
- etc...

What I'd love to see from the community [not clc but developers in
general] is just a sign of respect for the craft. Start off as a
student apprentice, write programs of all shapes and sizes, even
beyond the minimal lab work you have in school. Then as you progress,
adopt good practices, pass them off to others, etc...

Instead what you get are arrogant people with <1yr experience trying
to pass themselves off as "senior developers" who really have no
experience writing software, maintaining it, testing it, documenting
it, supporting it....

Tom
 
P

Processor-Dev1l

Processor-Dev1l said:
Processor-Dev1l wrote:
On Sep 22, 10:13 am, Nick Keighley <[email protected]>
wrote:
[...]
I just did a test on mainframe....
$ cat ctest.c
#include <stdio.h>
int main(void)
{
  int x;
  int y;
  x = 20;
  y = 35;
  x = y++ + x++;
  y = ++y + ++x;
  printf("x = %d, y = %d\n", x, y);
  return 0;}
[...]
$ ./a.out
x = 57, y = 94
$
Everything what I want is someone with linux to try it with gcc
compiler, that is
all.
why? It is Undefined Behaviour. Even changing the compiler
optimisation
level may change the result
Why? Because it works on USS cc modified compiler
"Gives the output I thought I wanted" is one of the possible outcomes of
undefined behavior.
I ran it on my DS3K, and it reformatted the hard drive.  Now I have to
reinstall everything.  Fortunately, the hardware itself is still intact.
...
It "formatted your hard drive"?
Well, I don't see any way how this code can format hard drive.

If you don't see how that can happen, that implies that you haven't
fully appreciated the significance of the part of the C standard which
says that when the behavior is undefined, "this International Standard
imposes no requirements". None. Nada. Zilch. Drill that into your
head. In some cases, something other than the ISO C standard may
impose relevant requirements (such as POSIX), in which case it may be
acceptable to write such code, so long as you only want to port it to
machines where that "something other" applies. However, unless
something else does impose relevant requirements, you should avoid
undefined behavior completely.

Unless, that is, you don't care what your program does. However, in
that case, why bother writing it in the first place? Not writing it,
and therefore not running it, is a lot easier, uses up less disk space
and less CPU time, and may have precisely the same effect as writing
it and executing it - "imposes no requirements" means that one of the
permitted results is that your program does absolutely nothing.

You may think "the standard may not impose any requirements, but
reality does - there's only a few realistic possibilities", but that's
an example of so-called "realism" gone soft in the brain. One of the
key purposes served by making the behavior undefined under certain
circumstances is that it allows implementions to implement various
optimizations without having to worry about the fact that those
optimizations might have unexpected consequences when applied to such
code. That means that such code has a good change of producing
arbitrarily bad unexpected consequences, as a result of such
optimizations.

Would you care to bet that you're able to anticipate every possible
way a compiler might choose to optimize your code, and thereby predict
what the consequences of those optimizations might be? Unless you have
been the sole author of a bleeding-edge aggressively optimizing C
compiler, I wouldn't recommend making such a bet, regardless of the
odds. Even if you were, the odds would have have to be pretty good to
justify such a bet.
Someone once said: Every program can be shorten by one useless line
and every program contains at least one wrong line.
It means you can shorten your code to one line that is wrong :).
Well, I don't work on new C compiler and I don't work with standard C
at all.
I work with modified C, which uses IBM compiler (made especially for
zOS system) for support of macros and system environment of zOS.
You're much better off making certain that you avoid writing any code
unless there is something, somewhere (it doesn't have to be the C
standard) which imposes some meaningful requirements on the behavior
of your code.
You mean except ATM machines, car industry, army, etc?
And quite frankly, it wasn't MY code, it was code of the original
poster (slightly modified two lines because I don't like int i = 0
definition).
Main reason why I thought this code can work is I spent really a lot
of times on HLL languages (like java, c#), where such constructions
are not undefined and they have their rules.

i = i++ + ++j;
but be translated by managed code as
++j;
i = i + j;
i++;

Now I know this is not C case and I am really sorry for the first
mistake, but various programming languages are messing my mind and
sometimes I am forgetting about differences.
 
D

Dik T. Winter

....
> 2 NOTE Possible undefined behavior ranges from ignoring the
> situation completely with unpredictable results, to behaving
> during translation or program execution in a documented manner
> characteristic of the environment (with or without the issuance
> of a diagnostic message), to terminating a translation or
> execution (with the issuance of a diagnostic message).

Note the last part, a compiler is even allowed not to compile the program
at all.
 
J

jameskuyper

Kenneth said:
jameskuyper wrote: .... ....
You may not consider a CPU "hard lock" a "realistic possibility", but I know
that, at least in early releases of some of those systems, it most certainly
was.

I assume that "You" referred to Processor-Dev1l? In context, it seems
to refer to me, but I was not advocating so narrow a view of the
realistic possibilities - quite the contrary.
 
J

jameskuyper

Processor-Dev1l said:
Well, I don't work on new C compiler and I don't work with standard C
at all.
I work with modified C, which uses IBM compiler (made especially for
zOS system) for support of macros and system environment of zOS.

If it's sufficiently modified to render the code in question safe, and
you're sufficiently uninterested in portability that you don't care
about the fact that it is unsafe in general then this is probably not
the best newsgroup for your discussions. You should find one that
specializes in writing deliberately and pointlessly non-portable code
targeted for that compiler.
You mean except ATM machines, car industry, army, etc?

No, I did not mean to make any exceptions for any of those application
areas; what I said is just as true for those areas as for my own
specialty, scientific data processing. It is true that in some of
those contexts, it is far more important than it is in my work, to
write code which relies upon something other than the C standard to
define the behavior of certain code constructs. However, there's no
point in even writing your code unless something defines it's
behavior, and that's just as true in those areas as in my own.
And quite frankly, it wasn't MY code, it was code of the original
poster (slightly modified two lines because I don't like int i = 0
definition).
Main reason why I thought this code can work is I spent really a lot
of times on HLL languages (like java, c#), where such constructions
are not undefined and they have their rules.

I understand that it's not your code - I'm not holding you responsible
for that. I understand that you didn't realize that it had undefined
behavior in C - there's nothing wrong with having something to learn;
we've all been there, many times.

What is problematic is your continued fascination with that code after
having learned that it has undefined behavior. The only rational
response to discovering that C code has undefined behavior is to fix
it, unless you know that there's something other than the C standard
which provides the definition that C itself does not.
 
K

Keith Thompson

Processor-Dev1l said:
Main reason why I thought this code can work is I spent really a lot
of times on HLL languages (like java, c#), where such constructions
are not undefined and they have their rules.

i = i++ + ++j;
but be translated by managed code as
++j;
i = i + j;
i++;

Now I know this is not C case and I am really sorry for the first
mistake, but various programming languages are messing my mind and
sometimes I am forgetting about differences.

Another question is this: Why would someone write that code in the
first place? C doesn't define what

i = i++ + ++j;

means, but whatever it was *intended* to mean, there's a simpler and
clearer way to write it (that also has the virtue of being
well-defined). For example:

i = i + ++j + 1;

I think a lot of programmers who are new to C become infatuated with
the powerful ++ and -- operators, and forget that (a) ++i is not the
same as i+1, and (b) i+1 is simpler and often just what you need,
and when i+1 is right, ++i is usually wrong.
 
S

Seebs

They should put something like BSD's strlcpy in the standard, that would
actually be useful.

I agree on this one. I wish strsep() and strlcpy() had made it in.

-s
 
K

Kenny McCormack

Keith Thompson said:
Another question is this: Why would someone write that code in the
first place? C doesn't define what

i = i++ + ++j;

means, but whatever it was *intended* to mean, there's a simpler and
clearer way to write it (that also has the virtue of being
well-defined). For example:

One of the goals of modern language design (a class of which C is not a
member) is to eliminate the concept of undefined behavior. It is a
necessary evil in C and assembler (and similar), but it is never
desirable. One of the primary goals of, to pick two unreleated but
similar examples, the 'D' programming language and 'C#' (and CLR
languages in general) was to make it that any legal syntax has one and
only one possible meaning. I.e., in the words of the 'D' implementor,
it is either correct or it isn't - none of this "in between" stuff
that characterizes C.

Now, you may agree with this or not, but the point is that that is what
the designers of these languages set out to do.
 
B

Ben Bacarisse

Processor-Dev1l said:
Main reason why I thought this code can work is I spent really a lot
of times on HLL languages (like java, c#), where such constructions
are not undefined and they have their rules.

i = i++ + ++j;
but be translated by managed code as
++j;
i = i + j;
i++;

Now rather OT... I accept that the above is defined in both Java and
C# but I don't think the two sequences are equivalent in either
language. I.e. it may be defined, but it is not defined as you seem
to think.
 
T

Tom St Denis

Tom St Denis wrote:

[...]
The problem really is that there a lot of people with arbitrary levels
of training and experience who call themselves developers.  To be a
professional developer you basically have to show some modicum of
understanding of the syntax.  I've seen quite a few developers who do
any number of classic development mistakes
- putting all your code in one large function

Feeping creatures have caused several of my functions to be larger than they
should be, and which have never been broken into several smaller functions.

Sometimes you can't logically break a process into reusable contents.
I have PKCS #8 code for instance where the encrypt function [which
handles multiple versions of the standard] is around 400 lines long.
Ideally I'd like to split that but you'd end up duplicating all of the
setup/fini code that it's not worth it.

But overall, my general rule of thumb is anything non-trivial that I
do more than once gets put on a list for "things I probably should re-
factor" which I then hit as I get time.

The point behind this one is it complicates smart linking [you get
more code than you may need in the image], it makes building take
longer, etc... It also makes it harder to work in a team since you
now have more resources locked up behind a cvs checkout.
Former offender.  Now rehabilitated.

This is just an organizational issue, but it helps once your project
grows beyond 2-3 files.
Not guilty.  (Though on multi-person projects, there will be a lack of
consistency between personal "styles" of indenting and braces.)

Agreed. You're rarely going to find a team that happily codes to the
exact same standard, but usually if you can't even roughly approximate
one another you're going to have problems.
On small functions, yes, sometimes.

For me it gets hard to read where things are initialized. For me I
initialize all the variables as soon as possible and group as many
together, I also line up the = signs... e.g.

Random snippet from some code I've written

prfbinding = NULL;
hashbinding = NULL;
hashidx = -1;
ciphermode = -1;
cipherbinding = -1;

It may seem a bit anal, but the code is really easy to read at a
glance, and it's much more tidy than say

prfbinding=NULL;
hashbinding=NULL;
hashidx=-1;
ciphermode=-1;
cipherbinding=-1;

It becomes habit to clean up the assignments so I rarely spend any
time thinking about doing it.
- tolerating obvious compiler warnings [like uninitialized variables,
undefined functions, etc]

Former offender.  Now mostly rehabilitated.

For me it's unacceptable to tolerate any reasonable and correct
warning. I do ignore some where they're just dead wrong, but
uninitialized variables [for instance] are usually correct. I say
usually because there are times where GCC incorrectly determines a
variable is uninitialized.
I don't think I ever check the return from fclose().  Does that count?

malloc(), on the other hand, is always checked in anything that's not a "run
this program once to see what the output is" type code.

Yeah fair enough, I don't check the return of fclose() either, but you
should check the return of the others. And I'm not talking strictly
standard C functions. In the crypto world where I live something as
simple as "sign this certificate" can go wrong for any number of
reasons. Yet I still find people that do something like

cert_sign(...);

go_on_your_way(...);

And it baffles me because they have no idea whether it worked or not
but just assume it did...

Tom
 
K

Keith Thompson

Tom St Denis said:
Yeah fair enough, I don't check the return of fclose() either, but you
should check the return of the others.
[...]

If fclose() fails on an input file, there's probably not much you
can sensibly do in response; I'm not even sure why fclose() on an
input file might fail (unless, say, you've already closed the file).

But fclose() *can* fail on an output file, and it could mean that
some of your data wasn't written.

Suppose your program is a text editor. The user does a
"save-file-and-quit" command. You write the contents of the editing
buffer to the user's file using fputs() or fwrite() or whatever.
The last output operation succeeds because it just copies the
data to the file buffer in memory. It's not until the fclose()
that the data is actually written to disk -- and that could fail
for any number of reasons (the disk is full, the device just
crashed, the server for the remote file system just went offline).
Silently quitting and telling the user his data was successfully
saved is not friendly behavior.

(Of course it's also possible that fclose() doesn't physically write
the data to the disk.)
 
J

jameskuyper

Tom said:
Tom St Denis wrote:

[...]
The problem really is that there a lot of people with arbitrary levels
of training and experience who call themselves developers. To be a
professional developer you basically have to show some modicum of
understanding of the syntax. I've seen quite a few developers who do
any number of classic development mistakes ....
- putting more than one exported function in a .c file

Guilty.

The point behind this one is it complicates smart linking [you get
more code than you may need in the image], it makes building take
longer, etc... It also makes it harder to work in a team since you
now have more resources locked up behind a cvs checkout.

Ah! I was wondering about that one. The only code that I myself have
designed which did that involved multiple functions that shared file
scope data with internal linkage. The way they were designed, it would
be almost completely pointless to write code that didn't call all of
the relevant functions (for instance, one function writes to the
shared date, the other reads it).

The reasons you give wouldn't apply to such code.
 
S

Seebs

One of the goals of modern language design (a class of which C is not a
member) is to eliminate the concept of undefined behavior. It is a
necessary evil in C and assembler (and similar), but it is never
desirable.

I am not convinced of this.
Now, you may agree with this or not, but the point is that that is what
the designers of these languages set out to do.

Yes, it is. And I am not sure they are making the right choice. There
is a very definite tradeoff there.

In C, if I want to ensure that operations occur in a specific order, or
at least appear to, I can. If I don't care what order they occur in,
though, I can also express that.

In a language with more rigidly defined semantics, there may be no way
for me to express "these three things need to happen, but I don't care
in what order."

-s
 
S

Seebs

There was an implied "all other things being equal" in there.

I guess I'd grant that undefined behavior is a bad thing, all other things
being equal, but since they can't be equal, I'm not convinced it's usefully
considered "bad". There are good reasons to have at the very least some
amount of "unspecified".

Actually, that might make a good boundary. "Undefined behavior" is probably
in general a bad thing, and should only exist if a language is operating at
a bare-metal level -- where you really are giving the processor incoherent
orders. "Unspecified behavior" is probably not a bad thing.

So it might make sense for a higher-level language to say "++i * ++i is either
i^2, i*(i+1), (i+1)^2, (i+1)*(i+2), i*(i+2), or (i+2)^2, and after it's
evaluated, i is definitely increased by 2, but we won't tell you what the
results will be." C just says "we have no clue, you could have just caused
your processor to deadlock." Requiring that the things recorded happen in
some order, and something come of it, but not being concrete as to exactly
what happens, would be safer but possibly produce slower code -- but in a
higher-level language, you're probably safe for other reasons. So the range
of possible explosions is much smaller, and probably fairly livable.

-s
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top