C chars_ptr STORAGE_ERROR in Imported function

This is a discussion on C chars_ptr STORAGE_ERROR in Imported function within the ADA forums in Programming Languages category; Hello there I am in progress of binding the pcap c library to ada, it is a part of a school project. And for that i need a funtion that modifies a parameter to a function like so: char *pcap_lookupdev(char *); I have figured out this much: function pcap_lookupdev(errbuff : Interfaces.C.Strings.Chars_Ptr) return Interfaces.C.Strings.Chars_Ptr; pragma Import (C, pcap_lookupdev, "pcap_lookupdev"); This works in the sense that running it as root returns the device found, but when I run it as normal user I get raised STORAGE_ERROR : stack overflow (or erroneous memory access) Do I need to declare the buffer and then ...

Go Back   Application Development Forum > Programming Languages > ADA

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-22-2008, 04:36 AM
Kim Rostgaard Christensen
Guest
 
Default C chars_ptr STORAGE_ERROR in Imported function

Hello there

I am in progress of binding the pcap c library to ada, it is a part of a
school project. And for that i need a funtion that modifies a parameter
to a function like so:

char *pcap_lookupdev(char *);

I have figured out this much:

function pcap_lookupdev(errbuff : Interfaces.C.Strings.Chars_Ptr)
return Interfaces.C.Strings.Chars_Ptr;
pragma Import (C, pcap_lookupdev, "pcap_lookupdev");

This works in the sense that running it as root returns the device
found, but when I run it as normal user I get

raised STORAGE_ERROR : stack overflow (or erroneous memory access)

Do I need to declare the buffer and then then pass its c pointer to the
function?

It is declared like this in a c example:
char errbuf[PCAP_ERRBUF_SIZE];

Best
Kim Rostgaard Christensen
Reply With Quote
  #2  
Old 08-22-2008, 05:03 AM
Niklas Holsti
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

Kim Rostgaard Christensen wrote:
> Hello there
>
> I am in progress of binding the pcap c library to ada, it is a part of a
> school project. And for that i need a funtion that modifies a parameter
> to a function like so:
>
> char *pcap_lookupdev(char *);
>

....
>
> Do I need to declare the buffer and then then pass its c pointer to the
> function?


That is certainly my interpretation of the "man" text:

char *pcap_lookupdev(char *errbuf)

pcap_lookupdev() returns a pointer to a network device
suitable for use with pcap_open_live() and pcap_lookupnet().
If there is an error, NULL is returned and errbuf is filled
in with an appropriate error message.

There is no hint that pcap_lookupdev() itself allocates the errbuf;
it just puts something in the caller-provided errbuf. And no doubt
places a NUL terminator after the message.

HTH

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Reply With Quote
  #3  
Old 08-22-2008, 05:55 AM
Kim Rostgaard Christensen
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

Niklas Holsti wrote:
> Kim Rostgaard Christensen wrote:
>> Hello there
>>
>> I am in progress of binding the pcap c library to ada, it is a part of a
>> school project. And for that i need a funtion that modifies a
>> parameter to a function like so:
>>
>> char *pcap_lookupdev(char *);
>>

> ...
>>
>> Do I need to declare the buffer and then then pass its c pointer to
>> the function?

>
> That is certainly my interpretation of the "man" text:
>
> char *pcap_lookupdev(char *errbuf)
>
> pcap_lookupdev() returns a pointer to a network device
> suitable for use with pcap_open_live() and pcap_lookupnet().
> If there is an error, NULL is returned and errbuf is filled
> in with an appropriate error message.
>
> There is no hint that pcap_lookupdev() itself allocates the errbuf; it
> just puts something in the caller-provided errbuf. And no doubt places a
> NUL terminator after the message.
>
> HTH
>


the following gives me
*** glibc detected *** double free or corruption (out): 0x0804d830 ***

raised PROGRAM_ERROR : unhandled signal

procedure Lookup_Device is
function pcap_lookupdev(ebuff : Interfaces.C.Strings.Chars_Ptr)
return Interfaces.C.Strings.Chars_Ptr;
pragma Import (C, pcap_lookupdev, "pcap_lookupdev");

Device : Interfaces.C.Strings.Chars_Ptr;
Errbuf_ptr : Interfaces.C.Strings.Chars_Ptr;
Errbuf : Char_Array(1 .. 256); -- the defined buffer size
begin
Errbuf_Ptr := New_Char_Array(Errbuf);
Device := pcap_lookupdev(Errbuf_ptr);

Ada.Text_IO.Put_Line(Value(Device));
end Lookup_Device;
Reply With Quote
  #4  
Old 08-22-2008, 07:43 AM
Niklas Holsti
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

Kim Rostgaard Christensen wrote:
> Niklas Holsti wrote:
>
>> Kim Rostgaard Christensen wrote:
>>
>>> Hello there
>>>
>>> I am in progress of binding the pcap c library to ada, it is a part of a
>>> school project. And for that i need a funtion that modifies a
>>> parameter to a function like so:
>>>
>>> char *pcap_lookupdev(char *);
>>>

...
>
> the following gives me
> *** glibc detected *** double free or corruption (out): 0x0804d830 ***
>
> raised PROGRAM_ERROR : unhandled signal
>
> procedure Lookup_Device is
> function pcap_lookupdev(ebuff : Interfaces.C.Strings.Chars_Ptr)
> return Interfaces.C.Strings.Chars_Ptr;
> pragma Import (C, pcap_lookupdev, "pcap_lookupdev");
>
> Device : Interfaces.C.Strings.Chars_Ptr;
> Errbuf_ptr : Interfaces.C.Strings.Chars_Ptr;
> Errbuf : Char_Array(1 .. 256); -- the defined buffer size
> begin


The problem is here:

> Errbuf_Ptr := New_Char_Array(Errbuf);


New_Char_Array allocates a new char_array object, containing only
the NUL-terminated string that is in Errbuf at this time. Since you
have left Errbuf uninitialized, this may be a lot less than 256
characters, so the errors are probably due to buffer overflow
somewhere in the pcap library where it tries to put an error
message into the char_array that Errrbuf_Ptr points to, but this
char_array is too small.

If you want to continue with New_Char_Array, you should initialize
Errbuf to contain a 256-character string:

Errbuf : Char_Array (1 .. 256) := (
others => Interfaces.C.To_C (' '));

or perhaps neater, but more complex, a NUL-terminated 255-character
string:

Errbuf : Char_Array (1 .. 256) := (
1 .. 255 => Interfaces.C.To_C (' '),
256 => Interfaces.C.nul);

Then New_Char_Array(Errbuf) will create a 256-character char_array
that has room for the error message. (It works for me.)

If you use New_Char_Array you should also deallocate the new
char_array by calling Interfaces.C.Strings.Free (Errbuf_Ptr) at a
suitable point, when you no longer need this char_array.

I think it would be better to use the To_Chars_Ptr function, which
makes a chars_ptr that points to Errbuf itself, without allocating
another char_array, so there is no need to Free anything. This also
needs a change in the declaration of Errbuf:

Errbuf : aliased Char_Array := (1 .. 256 => Interfaces.C.nul);

The initial values (here nul) are irrelevant, as long as there are
256 of them.

Then you replace the call of New_Char_Array with To_Chars_Ptr:

Errbuf_Ptr := To_Chars_Ptr (Errbuf'Unchecked_Access, False);

followed by:

> Device := pcap_lookupdev(Errbuf_ptr);


Also note that this can result in Device being a null pointer,
which will cause an error in the following:

> Ada.Text_IO.Put_Line(Value(Device));


so better check, like this:

if Device = Null_Ptr then

Put_Line ("Null device: " & Value (Errbuf_Ptr));

else

Put_Line ("Found device: " & Value (Device));

end if;

HTH

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Reply With Quote
  #5  
Old 08-22-2008, 02:48 PM
anon
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

Because Char_Prt in "Interfaces.C.Strings" is a private Ada type that
C function does not understand. You need to use "Interfaces.C.Pointer"
package to build a C Char_Ptr pointer package. And use those functions,
etc.

A possibility that most teachers may frown about, but it does work is to
switch the Ada pointers to "System.Address" and pass to the C functions..
Check out the "Interfaces.C.Extensions.ads" to see how the "void" and
"void *" are handled, if the teachers dislike the idea.


In <g8ltqo$7ir$1@jacob-sparre.dk>, Kim Rostgaard Christensen <krc@greenpc.dk> writes:
>Hello there
>
>I am in progress of binding the pcap c library to ada, it is a part of a
>school project. And for that i need a funtion that modifies a parameter
>to a function like so:
>
>char *pcap_lookupdev(char *);
>
>I have figured out this much:
>
> function pcap_lookupdev(errbuff : Interfaces.C.Strings.Chars_Ptr)
>return Interfaces.C.Strings.Chars_Ptr;
> pragma Import (C, pcap_lookupdev, "pcap_lookupdev");
>
>This works in the sense that running it as root returns the device
>found, but when I run it as normal user I get
>
>raised STORAGE_ERROR : stack overflow (or erroneous memory access)
>
>Do I need to declare the buffer and then then pass its c pointer to the
>function?
>
>It is declared like this in a c example:
>char errbuf[PCAP_ERRBUF_SIZE];
>
>Best
>Kim Rostgaard Christensen


Reply With Quote
  #6  
Old 08-22-2008, 05:55 PM
tmoran@acm.org
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

>A possibility that most teachers may frown about, but it does work is to
>switch the Ada pointers to "System.Address" and pass to the C functions..

That should be ".., but it may work on some versions of some compilers.."
Reply With Quote
  #7  
Old 08-22-2008, 06:54 PM
Kim Rostgaard Christensen
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

Niklas Holsti wrote:
....
> I think it would be better to use the To_Chars_Ptr function, which makes
> a chars_ptr that points to Errbuf itself, without allocating another
> char_array, so there is no need to Free anything. This also needs a
> change in the declaration of Errbuf:
>
> Errbuf : aliased Char_Array := (1 .. 256 => Interfaces.C.nul);
>

....
> Errbuf_Ptr := To_Chars_Ptr (Errbuf'Unchecked_Access, False);
>
> followed by:
>
>> Device := pcap_lookupdev(Errbuf_ptr);

>

....
> HTH
>


This works like a charm, thanks a lot.

KRC
Reply With Quote
  #8  
Old 08-23-2008, 06:11 AM
Niklas Holsti
Guest
 
Default Re: C chars_ptr STORAGE_ERROR in Imported function

(Top posting by "anon" changed to bottom style...)

anon wrote:
> In <g8ltqo$7ir$1@jacob-sparre.dk>, Kim Rostgaard Christensen
> <krc@greenpc.dk> writes:
>
>>Hello there
>>
>>I am in progress of binding the pcap c library to ada, it is a
>>part of a school project. And for that i need a funtion that
>>modifies a parameter to a function like so:
>>
>>char *pcap_lookupdev(char *);
>>
>>I have figured out this much:
>>
>> function pcap_lookupdev(errbuff :

Interfaces.C.Strings.Chars_Ptr)
>> return Interfaces.C.Strings.Chars_Ptr;
>> pragma Import (C, pcap_lookupdev, "pcap_lookupdev");
>>
>>This works in the sense that running it as root returns the
>>device found, but when I run it as normal user I get
>>raised STORAGE_ERROR : stack overflow (or erroneous memory
>>access)
>>
>>Do I need to declare the buffer and then then pass its c pointer
>>to the function?


anon wrote:
> Because Char_Prt in "Interfaces.C.Strings" is a private Ada
> type that C function does not understand.


No, that's wrong. RM B.3.1(1) says that

....the private type chars_ptr corresponds to a common use of "char
*" in C programs, and an object of this type can be passed to a
subprogram to which pragma Import(C,...) has been applied, and for
which "char *" is the type of the argument of the C function.

I think Kim's choice of chars_ptr for this parameter is correct.
The error was firstly in the use of an uninitialized parameter of
this type (default initialized to Null_Ptr), and secondly in using
New_Char_Array on an uninitialized char_array, making
New_Char_Array allocate a smaller new buffer than was needed to
hold the error message from pcap_lookupdev(). Thus,
pcap_lookupdev() was called with incorrect values of its parameter,
not with an incorrect type of parameter. Similar errors could have
been made in a C function calling pcap_lookupdev() with a C
parameter of type "char *".

> You need to use "Interfaces.C.Pointer" package to build a C
> Char_Ptr pointer package.


That might work, too, but Interfaces.C.Strings is the right tool
for pcap_lookupdev() since the parameter really is a NUL-terminated
C-style string.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 02:57 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.