Hi all,
Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
regards,
jayapal.
Nov 16 '07
104 5281
CBFalconer wrote, On 24/11/07 22:52:
$)CHarald van D)&k wrote:
>CBFalconer wrote:
>>So here is another. Imagine a routine to upshift a string. One routine receives a char, and answere with 'this is lower case'. Another receives a char, and answers by replacing it with the upper case equivalent. Both are passed pointers.
Assuming the original data is a string, the calling routine will pass something like:
p = &(s[3]); or p = s + 3; (p is parameter)
For the reading routine, there is no harm in allowing reads from (p - n), where n can be 0 through 3. For the writing routine, this is not allowable.
Why not? Is it because the behaviour would be undefined, or is it because the function's actions would be different from its description? If the former, I'm not seeing it, so could you please explain? If the latter, as long as it's valid C, there's no reason why an implementation would or should complain about it.
Because a char was passed, not an array.
No, a pointer to char was passed, and that is a pointer to a byte within
a larger object.
So a means has to be
found to separate the two.
No, because C does not have a distinction between a pointer to an
element of an array and a pointer to a single object.
Remember that the system is pointless
unless it works all the time.
That is a good argument for getting rid of *all* safety features
everywhere. So go back to DOS because the memory protection in Windows
does not work all the time (otherwise we would not be talking about
whether fat pointers can improve protection), get rid of lifeboats from
cruise ships because sometimes they fail and so on. Not to mention your
ggets routine being pointless because it fails if someone feeds it a
line longer than it can successfully allocate memory for.
--
Flash Gordon
CBFalconer wrote:
Chris Torek wrote:
>Richard Bos <rl*@hoekstra-uitgeverij.nlwr ote:
>>... you do need to link fat-pointer-compiled object files with fat-pointer-compiled libraries; much as you need to link 64-bit object files with 64-bit libraries, little-endian object files with little-endian libraries, and on MS-DOS used to link large memory model object files with large memory model libraries.
... snip ...
>In general, the simplest method is to have all "fat pointers" represented as a triple: <currentvalue , base, limit>. A pointer is "valid" if its current-value is at least as big as its base and no bigger than its limit:
Just picking on one thing, based on it has to work everywhere, or
it is useless.
We're talking about use of fat pointers as a device to protect against
memory bounds violation. Protection doesn't have to be perfect to be
useful. A bullet-proof vest won't protect against a head shot, washing
your hands before a meal won't protect you against airborne diseases,
the best available contraceptive measures still occasionally fail. That
doesn't make those protective measures useless.
A simple, relatively straightforward fat pointer implementation that is
only moderately inefficient can't protect against every possible
problem. It could protect against use of pointer arithmetic to create a
pointer to a position before the beginning, or more than one position
after the end, of the relevant array. It can also protect against any
attempt to access positions one past the end of the array. Providing
more complete protection requires a more complicated or inefficient
mechanism; but that doesn't make the simpler protection mechanism useless.
....
I have made my share of mistakes in code-generation, and I want
things simple and consistent.
Fat pointers are not as simple to implement as ordinary pointers, and I
would imagine that retrofitting an implementation originally designed to
use ordinary pointers would be a bug-prone process. However, it's
nowhere near to being the most complicated feature that real C compilers
have implemented successfully.
"Chris Torek" <no****@torek.n etwrote in message
>When dealing with pointers to objects embedded within larger objects (such as elements of "struct"s), the simplest method is again to widen the base-and-limit to encompass the large object. Consider, e.g.:
% cat derived.c
#include "base.h"
struct derived {
struct base common;
int additional;
};
void basefunc(struct base *, void (*)(struct base *)); /* in base.c */
static void subfunc(struct base *);
void func(void) {
struct derived var;
...
basefunc(&var.c ommon, subfunc);
...
}
static void subfunc(struct base *p0) {
struct derived *p = (struct derived *)p0; /* line X */
... use p->common and p->additional here ...
}
>There is clearly no problem in the call to basefunc(), even if we "narrow" the "fat pointer" to point only to the sub-structure &var.common. However, when basefunc() "calls back" into subfunc(), as presumably it will, with a "fat pointer" to the "common" part of a "struct derived", we will have to "re-widen" the pointer. We can do that at the point of the cast (line X), or simply avoid "narrowing" the fat pointer at the call to basefunc(), so that when basefunc() calls subfunc(), it passes a pointer to the entire structure "var", rather than just var.common.
(It is probably the case, not that I have thought about it that
much, that we can pass only the "fully widened to entire object"
pointer if we are taking the address of the *first* element of
the structure. That is, C code of the form:
You've missed the problem
struct gandma
{
struct mother first[3];
int x;
};
struct mother
{
char child[3];
int x;
};
struct grandma grannies[3];
char *fatkid = &grannies[1].first[1].child;
/* fatkid ought to have bounds between child and child + 3 */
struct grandma *fatoldlady = (struct grandma *) fatkid;
/* fat old lady points tot he middle of an array, it needs bounds
grannies[0] to
grannies[2] */
It's hard to supoort this
You need a "mother pointer" to give the bounds of the containing structure,
purely to support upcasts. That can have its own mother pointer. All in all,
too much trouble purely to support one little-used construct.
struct fatpointer{
void *base;
void *upper;
void *ptr;
struct fatpointer *mother;
};
The real answer is to ban subtractions or additions to upcast pointers.
--
Free games and programming goodies. http://www.personal.leeds.ac.uk/~bgy1mm
James Kuyper wrote:
CBFalconer wrote:
>Chris Torek wrote:
>>Richard Bos <rl*@hoekstra-uitgeverij.nlwr ote:
... you do need to link fat-pointer-compiled object files with fat-pointer-compiled libraries; much as you need to link 64-bit object files with 64-bit libraries, little-endian object files with little-endian libraries, and on MS-DOS used to link large memory model object files with large memory model libraries.
... snip ...
>>In general, the simplest method is to have all "fat pointers" represented as a triple: <currentvalue , base, limit>. A pointer is "valid" if its current-value is at least as big as its base and no bigger than its limit:
Just picking on one thing, based on it has to work everywhere, or it is useless.
We're talking about use of fat pointers as a device to protect against
memory bounds violation. Protection doesn't have to be perfect to be
useful. A bullet-proof vest won't protect against a head shot, washing
your hands before a meal won't protect you against airborne diseases,
the best available contraceptive measures still occasionally fail. That
doesn't make those protective measures useless.
A simple, relatively straightforward fat pointer implementation that is
only moderately inefficient can't protect against every possible
problem. It could protect against use of pointer arithmetic to create a
pointer to a position before the beginning, or more than one position
after the end, of the relevant array. It can also protect against any
attempt to access positions one past the end of the array. Providing
more complete protection requires a more complicated or inefficient
mechanism; but that doesn't make the simpler protection mechanism useless.
...
>I have made my share of mistakes in code-generation, and I want things simple and consistent.
Fat pointers are not as simple to implement as ordinary pointers, and I
would imagine that retrofitting an implementation originally designed to
use ordinary pointers would be a bug-prone process. However, it's
nowhere near to being the most complicated feature that real C compilers
have implemented successfully.
I think my major point is that, wherever I look, I see continuously
building auxiliary data combined with cpu-eating indirect pointer
accesses.
I also maintain that it has to work all the time. Otherwise the
fact that it passes gives one no confidence whatsoever, and the odd
pass just encourages ignoring the real problem. How many time do
you hear 'It works on my machine' as the excuse/justification for
poor code?
--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home .att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com
Flash Gordon wrote:
CBFalconer wrote, On 24/11/07 22:52:
>$)CHarald van D)&k wrote:
>>CBFalconer wrote:
So here is another. Imagine a routine to upshift a string. One routine receives a char, and answere with 'this is lower case'. Another receives a char, and answers by replacing it with the upper case equivalent. Both are passed pointers.
Assuming the original data is a string, the calling routine will pass something like:
p = &(s[3]); or p = s + 3; (p is parameter)
For the reading routine, there is no harm in allowing reads from (p - n), where n can be 0 through 3. For the writing routine, this is not allowable.
Why not? Is it because the behaviour would be undefined, or is it because the function's actions would be different from its description ? If the former, I'm not seeing it, so could you please explain? If the latter, as long as it's valid C, there's no reason why an implementation would or should complain about it.
Because a char was passed, not an array.
No, a pointer to char was passed, and that is a pointer to a byte
within a larger object.
>So a means has to be found to separate the two.
No, because C does not have a distinction between a pointer to an
element of an array and a pointer to a single object.
Exactly. So the only way to pass that distinction is through the
pointer. This involves revising the pointer on every pass. The
data builds and builds, as does the overhead. Don't forget that
the old pointer must be retained, because the called routine will
presumably return.
--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home .att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com
"CBFalconer " <cb********@yah oo.comwrote in message
I think my major point is that, wherever I look, I see continuously
building auxiliary data combined with cpu-eating indirect pointer
accesses.
I also maintain that it has to work all the time. Otherwise the
fact that it passes gives one no confidence whatsoever, and the odd
pass just encourages ignoring the real problem. How many time do
you hear 'It works on my machine' as the excuse/justification for
poor code?
A wild pointer read, write or even calculation renders the program
undefined. Undefined by the C standard, that is, not in some philosphical
state of undefinedness.
If we define it as always printing out to stderr an error message, and
terminating, rather than doing something funny, like corrupting an
instruction in an unrelatred part of the program, or appearing to work as
intended, it is much easiser for a debugger to catch bugs.
The tool is far more useful if it catches every case. However this cannot be
achieved in practise. For instance a recent bug in our code - actually
written in Fortran, went
double energy[12]; /* set up to statistical free energy levels */
for(i=0;i<12;i+ +)
if(theta erange[i] && theta <= erange[i+1])
index = i;
totenergy += energy[index];
of course if theta is not in any of the ranges, UB will result. However the
ranges went from 0 degrees to 160 degrees, and you tend not to get straight
bonds. So it could run for some time until the calculation went wrong.
After a few debug passes, you run code for real with thin pointers. The
runtime overhead is acceptable for some applications, but not the ones C
tends to be used for.
--
Free games and programming goodies. http://www.personal.leeds.ac.uk/~bgy1mm
CBFalconer wrote:
James Kuyper wrote:
>CBFalconer wrote:
....
>>Just picking on one thing, based on it has to work everywhere, or it is useless.
We're talking about use of fat pointers as a device to protect against memory bounds violation. Protection doesn't have to be perfect to be useful. A bullet-proof vest won't protect against a head shot, ...
....
I think my major point is that, wherever I look, I see continuously
building auxiliary data combined with cpu-eating indirect pointer
accesses.
That depends upon your concept that it has to be a perfect to be useful.
Embrace the fact that it can still be useful if imperfect, and a much
simpler implementation becomes possible that merely seriously impairs
efficiency, rather than completely destroying it.
All that's needed to provide substantial protection is pointers that
carry a base address, an end address, and a current address, and a
compiler that sets those addresses appropriately whenever an expression
has a value of pointer type.
I also maintain that it has to work all the time. Otherwise the
fact that it passes gives one no confidence whatsoever, and the odd
pass just encourages ignoring the real problem.
By the same logic, to apply my previous analogy, a bullet proof vest has
to work against all bullets, or it's useless. If it doesn't it gives you
no confidence whatsoever that you are safe from bullets, and the odd
pass just encourages ignoring the real problem, which is that people are
shooting at you. That's a clearly ridiculous argument; and the reason is
the logic, not the analogy.
The fat pointers we're discussing aren't supposed to give you confidence
that your code has no errors. They're supposed to help you detect
certain kinds of errors, so you can deal with them. The fact that they
can't catch all possible errors is perfectly normal for error detection
techniques.
CBFalconer wrote, On 25/11/07 16:20:
Flash Gordon wrote:
>CBFalconer wrote, On 24/11/07 22:52:
>>$)CHarald van D)&k wrote: CBFalconer wrote:
So here is another. Imagine a routine to upshift a string. One routine receives a char, and answere with 'this is lower case'. Another receives a char, and answers by replacing it with the upper case equivalent. Both are passed pointers. > Assuming the original data is a string, the calling routine will pass something like: > p = &(s[3]); or p = s + 3; (p is parameter) > For the reading routine, there is no harm in allowing reads from (p - n), where n can be 0 through 3. For the writing routine, this is not allowable. Why not? Is it because the behaviour would be undefined, or is it because the function's actions would be different from its descriptio n? If the former, I'm not seeing it, so could you please explain? If the latter, as long as it's valid C, there's no reason why an implementation would or should complain about it. Because a char was passed, not an array.
No, a pointer to char was passed, and that is a pointer to a byte within a larger object.
>>So a means has to be found to separate the two.
No, because C does not have a distinction between a pointer to an element of an array and a pointer to a single object.
Exactly. So the only way to pass that distinction is through the
pointer.
No, the only way is to accept that there is no distinction.
This involves revising the pointer on every pass.
No, it involves passing exactly the same data all the way down.
The
data builds and builds, as does the overhead. Don't forget that
the old pointer must be retained, because the called routine will
presumably return.
I honestly cannot see what you are getting at. However many functions
the pointer is passed through there is no additional overhead because it
is always valid to access any part of the parent object. Anything else
and you are talking about how useful fat pointers would be for a
language other than C, and no one else is talking about anything other
than what a conforming C implementation could do.
--
Flash Gordon
"James Kuyper" <ja*********@ve rizon.netwrote in message
By the same logic, to apply my previous analogy, a bullet proof vest has
to work against all bullets, or it's useless. If it doesn't it gives you
no confidence whatsoever that you are safe from bullets, and the odd pass
just encourages ignoring the real problem, which is that people are
shooting at you. That's a clearly ridiculous argument; and the reason is
the logic, not the analogy.
If a competing vest offers 100% protection then your vest, offering 99%,
will need to be very much cheaper indeed before it will find a market.
However in the absence of anything better, even 50% protection is much
better than nothing.
--
Free games and programming goodies. http://www.personal.leeds.ac.uk/~bgy1mm
Flash Gordon wrote:
CBFalconer wrote:
>Flash Gordon wrote:
.... snip ...
>>
>>No, because C does not have a distinction between a pointer to an element of an array and a pointer to a single object.
Exactly. So the only way to pass that distinction is through the pointer.
No, the only way is to accept that there is no distinction.
>This involves revising the pointer on every pass.
No, it involves passing exactly the same data all the way down.
>The data builds and builds, as does the overhead. Don't forget that the old pointer must be retained, because the called routine will presumably return.
I honestly cannot see what you are getting at. However many
functions the pointer is passed through there is no additional
overhead because it is always valid to access any part of the
parent object. Anything else and you are talking about how useful
fat pointers would be for a language other than C, and no one
else is talking about anything other than what a conforming C
implementation could do.
Just as an example, imagine some idiot designed a function that
operated on two strings known to be stored DIFF bytes apart. That
function is passed a single pointer, as in:
char foo(char *bar) {
char ch;
if (islower(*bar)) *(bar + DIFF) = toupper(*bar);
else *(bar + DIFF) = *bar;
/* now exchange chars */
ch = *bar; *bar = *(bar + DIFF); *(bar + DIFF) = ch;
return ch;
} /* foo */
Now this silly function has a name that makes it seem to upshift
chars in a string. It passes all tests, because of the use of the
magic value of DIFF. Somebody procedes to use it again. All sorts
of things blow up. The function is ignored, because it passes the
tests in the original, and it is in a library, and never got
recompiled. Don't forget that it has been stamped as VALIDATED in
upper case.
I don't want this form of 'checking'.
NOTE: I am pulling up various weird code to show that there are
problems. I have not tried for any consistency.
--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home .att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Michael Sig Birkmose |
last post by:
Hi everyone!
Does anyone know, if it is possible to meassure the maximum stack usage of
a C program throughout it's entire execution?
--
Michael Birkmose
|
by: Lee |
last post by:
Hi
Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). Is this due to the
possibility of array overflow? Is it correct that the program flow can
be altered by giving some specific calculated inputs to gets()? How
could anyone do so once the executable binary have been generated? I
have heard many of the security problems and other bugs are due to
array overflows.
|
by: Cuthbert |
last post by:
After compiling the source code with gcc v.4.1.1, I got a warning
message:
"/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
'gets' function is dangerous and should not be used."
Could anybody tell me why gets() function is dangerous??
Thank you very much.
Cuthbert
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
| |
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,...
|
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...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
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();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |