Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000074 [1003.1(2008)/Issue 7] System Interfaces Objection Error 2009-06-29 02:27 2013-04-16 13:06
Reporter nick View Status public  
Assigned To ajosey
Priority normal Resolution Accepted As Marked  
Status Closed  
Name Nick Stoughton
Organization
User Reference
Section Pointer
Page Number 541
Line Number 18886
Interp Status Approved
Final Accepted Text Note: 0000205
Summary 0000074: Pointer Types Problem
Description _____________________________________________________________________________
 OBJECTION Enhancement Request Number 11
 nick:xxxxxxxxxx Bug in XSHd5.1 Pointer Types (rdvk# 1)
 {NMS-funcptr} Wed, 10 Sep 2008 21:05:32 +0100 (BST)
 _____________________________________________________________________________

In order to support the dynamic library functions (and dlsym() in
 particular), POSIX extends the C standard to require that a
 pointer to a function can be stored in a pointer to void.

 This explicit extension opens the door to permit conversion (via other
 promises in the C standard) of a pointer to a data object
 into a pointer to a function, thus requiring code such as below

 to work:

 char buf[1024];
 void *p;
 int (*f)(void);

 // assemble instructions into buf
 p = buf;
 f = p;
 f();


 In practice, many implementations will forbid execution of data
 in this form, as it is frequently a source of security vulnerabilities.

 Similarly, it need not necessarily be supported to try to examine
 the instructions that make a function by casting (or converting via
 a void *) a pointer-to-function into a pointer-to-object.

 The intent is simply to permit dlsym to use a void * as its return type.
Desired Action After the sentence ending on line 18890, add the following:

 If a pointer to an object or incomplete type is converted to a pointer
 to void and then to a pointer to a function type, or vice-versa,
 the behaviour is undefined.
Tags c99, tc1-2008
Attached Files

- Relationships
has duplicate 0000178Closedajosey Online Pubs dlsym page has slightly broken style when referring to dlopen()/dlerror() 
has duplicate 0000099Closedajosey 1003.1(2008)/Issue 7 dlopen return on success 
has duplicate 0000100Closedajosey 1003.1(2008)/Issue 7 dlsym return on success 
related to 0000829Closed 1003.1(2013)/Issue7+TC1 Change XSH/TC1/D5/0017 [74] removed the corresponding normative text 
related to 0001439Closed 1003.1(2016/18)/Issue7+TC2 The POSIX standard did not distinguish object and function pointers as did the C standard. 
related to 0001644Applied 1003.1(2016/18)/Issue7+TC2 void * to function pointer is described in annex J of C standard (informative). 

-  Notes
(0000129)
msbrown (manager)
2009-06-29 02:27

After the sentence ending on line 18890, add the following:

If a pointer to an object or incomplete type is converted to a pointer
to void and then to a pointer to a function type the behavior
is undefined., If a pointer to a function type is converted to
a pointer to void and then to a pointer to an object or an incomplete
type the behaviour is undefined.
(0000155)
Konrad_Schwarz (reporter)
2009-07-07 07:23
edited on: 2009-07-07 08:13

In the description of dlsym() (lines 24689--24764), replace all occurrences of "object(s)" with "executable object file(s)" or "object file(s)", for consistency with dlopen() and because "object" has a different meaning in C. The same applies to dlclose() (lines 24469--24526) and to the later paragraphs of dlopen() (lines 24594--24688).

Also, it should be clarified that a "symbol" is either a function or a (data) object. In line 24659, replace "shall be those that were" by "shall be the functions and objects that were".

(0000156)
Konrad_Schwarz (reporter)
2009-07-07 08:38

As an alternative suggestion to note 129, which led to much discussion on the E-mail reflector, add after the first sentence of dlsym()'s DESCRIPTION (line 24696):

dlsym()'s return value, cast to a pointer to the type of the symbol, may be used to call (in case of a function) respectively access (in case of a [data] object) the symbol.

Section 2.12.3 could then be struck completely; section RATIONAL of dlsym() would need to be adjusted, e.g., by striking lines 24742--24785.
(0000203)
Don Cragun (manager)
2009-08-20 21:18

After further discussion on this issue, it has been reopened.
The descriptions of dlclose(), dlopen(), and dlsym() are being rewritten
to be more consistent with terminology used in the C standard and with
the use of symbol in the rest of this standard. When done, it is also
expected that 0000100 will be closed as a duplicate of this problem
and the changes here will fix both issues.

It is also expected that this issue will need to go down the
interpretations track as a DEFECT situation.
(0000205)
Don Cragun (manager)
2009-08-27 00:03
edited on: 2009-11-06 06:52

Interpretation response
------------------------
The standard states the requirements for pointer types , and
conforming implementations must conform to this. However, concerns have
been raised about this which are being referred to the sponsor.

Rationale:
-------------
None.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------


After a lengthy discussion on the e-mail list based on the proposed
resolution in Note: 0000129, the committee decided to revise the text.
These changes solve:
1.  the issue initially raised in this report,
2.  the issue raised in 0000099 (which will be closed as a dup of
    this bug when this bug resolution is approved),
3.  the issue raised in 0000100 (which will be closed as a dup of
    this bug when this bug resolution is approved),
4.  some inconsistencies between the uses of the term object in this
    standard and in ISO C (as noted by Konrad in Note: 0000155 and
    Note: 0000156), and
5.  the inconsistent use of the term symbol in this standard (in the
    rest of this standard, symbol refers either to a graphic
    representation of a character or to a symbolic constant; in the
    description of dlsym(), however, symbol refers to what is known by
    the term identifier in ISO C.

This note was discussed during the August 27, 2009 conference call and
minor edits have made done in place (without creating a new note).

------------------------------------------------------------------------

Delete subclause 2.12.3 from P541, L18881-18886.

------------------------------------------------------------------------

Replace the NAME, SYNOPSIS, DESCRIPTION, RETURN VALUE, ERRORS, EXAMPLES,
and APPLICATION USAGE sections of the dlclose() descripion on P728,
L24469-24513 with:

NAME
        dlclose -- close a symbol table handle

SYNOPSIS
        #include <dlfcn.h>
        int dlclose(void *handle);

DESCRIPTION
        The dlclose() function shall inform the system that the symbol
        table handle specified by handle is no longer needed by the
        application.

        An application writer may use dlclose() to make a statement of
        intent on the part of the process, but this statemen does not
        create any requirement upon the implementation.  When the symbol
        table handle is closed, the implementation may unload the
        executable object files that were loaded by dlopen() when the
        symbol table handle was opened and those that were loaded by
        dlsym() when using the symbol table handle identified by handle.
        Once a symbol table handle has been closed, an application
        should assume that any symbols (function identifiers and data
        object identifiers) made visible using handle, are no longer
        available to the process.

        Although a dlclose() operation is not required to remove any
        functions or data objects from the address space, neither is an
        implementation prohibited from doing so.  The only restriction
        on such a removal is that no function nor data object shall be
        removed to which references have been relocated, until or unless
        all such references are removed.  For instance, an executable
        object file that had been loaded with a dlopen() operation
        specifying the RTLD_GLOBAL flag might provide a target for
        dynamic relocations performed in the processing of other
        relocatable objects--in such environments, an application may
        assume that no relocation, once made, shall be undone or remade
        unless the executable object file containing the relocated
        object has itself been removed.

RETURN VALUE
        If the referenced symbol table handle was successfully closed,
        dlclose() shall return 0.  If handle does not refer to an open
        symbol table handle or if the symbol table handle could not be
        closed, dlclose() shall return a non-zero value.  More detailed
        diagnostic information shall be available through dlerror().

ERRORS
        No errors are defined.

EXAMPLES
        The following example illustrates use of dlopen() and dlclose():

        #include <dlfcn.h>
        int     eret;
        void    *mylib;
        ...
        /* Open a dynamic library and then close it ... */
        mylib = dlopen("mylib.so", RTLD_LOCAL | RTLD_LAZY);
        ...
        eret = dlclose(mylib);
        ...

APPLICATION USAGE
        A conforming application should employ a symbol table handle
        returned from a dlopen() invocation only within a given scope
        bracketed by a dlopen() operation and the corresponding
        dlclose() operation.  Implementations are free to use reference
        counting or other techniques such that multiple calls to
        dlopen() referencing the same executable object file may return
        a pointer to the same data object as the symbol table handle.
        Implementations are also free to reuse a handle.  For these
        reasons, the value of a handle must be treated as an opaque data
        type by the application, used only in calls to dlsym() and
        dlclose().

------------------------------------------------------------------------

Replace the NAME, SYNOPSIS, DESCRIPTION, and RETURN VALUE sections of
the dlopen() descripion on P732-733, L24575-24666:

NAME
        dlopen -- open a symbol table handle

SYNOPSIS
        #include <dlfcn.h>
        void *dlopen(const char *file, int mode);

DESCRIPTION
        The dlopen() function shall make the symbols (function
        identifiers and data object identifiers) in the executable
        object file specified by file available to the calling program.
        The class of executable object files eligible for this operation
        and the manner of their construction are implementation-defined,
        though typically such files are shared libraries or programs.
        Implementations may permit the construction of embedded
        dependencies in executable object files.  In such cases, a
        dlopen() operation shall load those dependencies in addition to
        the executable object file specified by file.  Implementations
        may also impose specific constraints on the construction of
        programs that can employ dlopen() and its related services.

        A successful dlopen() shall return a symbol table handle which
        the caller may use on subsequent calls to dlsym() and dlclose().
        The value of this symbol table handle should not be interpreted
        in any way by the caller.

        The file argument is used to construct a pathname to the
        executable object file.  If file contains a <slash> character,
        the file argument is used as the pathname for the file.
        Otherwise, file is used in an implementation-defined manner to
        yield a pathname.

        If file is a null pointer, dlopen() shall return a global symbol
        table handle for the currently running process image.  This
        symbol table handle shall provide access to the symbols from an
        ordered set of executable object files consisting of the
        original program image file, any executable object files loaded
        at program start-up as specified by that process image file (for
        example, shared libraries), and the set of executable object
        files loaded using dlopen() operations with the RTLD_GLOBAL
        flag.  As the latter set of executable object files can change
        during execution, the set of symbols made available by this
        symbol table handle can also change dynamically.

        Only a single copy of an executable object file shall be brought
        into the address space, even if dlopen() is invoked multiple
        times in reference to the executable object file, and even if
        different pathnames are used to reference the executable object
        file.

        The mode parameter describes how dlopen() shall operate upon
        file with respect to the processing of relocations and the scope
        of visibility of the symbols provided within file.  When an
        executable object file is brought into the address space of a
        process, it may contain references to symbols whose addresses
        are not known until the executable object file is loaded.
        These references shall be relocated before the symbols can be
        accessed.  The mode parameter governs when these relocations
        take place and may have the following values:

        RTLD_LAZY       Relocations shall be performed at an
                        implementation-defined time, ranging from the
                        time of the dlopen() call until the first
                        reference to a given symbol occurs.  Specifying
                        RTLD_LAZY should improve performance on
                        implementations supporting dynamic symbol
                        binding since a process might not reference all
                        of the symbols in an executable object file.
                        And, for systems supporting dynamic symbol
                        resolution for normal process execution, this
                        behavior mimics the normal handling of process
                        execution.

        RTLD_NOW        All necessary relocations shall be performed
                        when the executable object file is first loaded.
                        This may waste some processing if relocations
                        are performed for symbols that are never
                        referenced.  This behavior may be useful for
                        applications that need to know that all symbols
                        referenced during execution will be available
                        before dlopen() returns.

        Any executable object file loaded by dlopen() that requires
        relocations against global symbols can reference the symbols in
        the original process image file, any executable object files
        loaded at program start-up, from the initial process image
        itself, from any other executable object file included in the
        same dlopen() invocation, and any executable object files that
        were loaded in any dlopen() invocation and which specified the
        RTLD_GLOBAL flag.  To determine the scope of visibility for the
        symbols loaded with a dlopen() invocation, the mode parameter
        should be a bitwise-inclusive OR with one of the following
        values:

        RTLD_GLOBAL     The executable object file's symbols shall be
                        made available for relocation processing of any
                        other executable object file.  In addition,
                        symbol lookup using dlopen(NULL, mode) and an
                        associated dlsym() allows executable object
                        files loaded with this mode to be searched.

        RTLD_LOCAL      The executable object file's symbols shall not
                        be made available for relocation processing of
                        any other executable object file.

        If neither RTLD_GLOBAL nor RTLD_LOCAL are specified, the default
        behavior is unspecified.

        If an executable object file is specified in multiple dlopen()
        invocations, mode is interpreted at each invocation.
        If RTLD_NOW has been specified, all relocations
        shall have been completed rendering further RTLD_NOW operations
        redundant and any further RTLD_LAZY operations irrelevant.
    If RTLD_GLOBAL has been specified, the executable object file
    shall maintain the RTLD_GLOBAL status regardless of any previous
    or future specification of RTLD_LOCAL, as long as the executable
    object file remains in the address space (see dlclose()).

        Symbols introduced into the process image through calls to
        dlopen() may be used in relocation activities.  Symbols so
        introduced may duplicate symbols already defined by the program
        or previous dlopen() operations.  To resolve the ambiguities
        such a situation might present, the resolution of a symbol
        reference to symbol definition is based on a symbol resolution
        order.  Two such resolution orders are defined: load order and
        dependency order.  Load order establishes an ordering among
        symbol definitions, such that the first definition loaded
        (including definitions from the process image file and any
        dependent executable object files loaded with it) has priority
        over executable object files added later (by dlopen()).  Load
        ordering is used in relocation processing.  Dependency ordering
        uses a breadth-first order starting with a given executable
        object file, then all of its dependencies, then any dependents
        of those, iterating until all dependencies are satisfied.  With
        the exception of the global symbol table handle obtained via a
        dlopen() operation with a null pointer as the file argument,
        dependency ordering is used by the dlsym() function.  Load
        ordering is used in dlsym() operations upon the global symbol
        table handle.

        When an executable object file is first made accessible via
        dlopen(), it and its dependent executable object files are added
        in dependency order.  Once all the executable object files are
        added, relocations are performed using load order.  Note that if
        an executable object file or its dependencies had been
        previously loaded, the load and dependency orders may yield
        different resolutions.

        The symbols introduced by dlopen() operations and available
        through dlsym() are at a minimum those which are exported as
        identifiers of global scope by the executable object file.
        Typically such identifiers shall be those that were specified in
        (for example) C source code as having extern linkage.  The
        precise manner in which an implementation constructs the set of
        exported symbols for an executable object file is
        implementation-defined.

RETURN VALUE
        Upon successful completion, dlopen() shall return a symbol table
        handle.  If file cannot be found, cannot be opened for reading,
        is not of an appropriate executable object file format for
        processing by dlopen(), or if an error occurs during the process
        of loading file or relocating its symbolic references, dlopen()
    shall return a null pointer.  More detailed diagnostic
    information shall be available through dlerror().

------------------------------------------------------------------------

Replace the NAME, SYNOPSIS, DESCRIPTION, RETURN VALUE, ERRORS, EXAMPLES,
APPLICATION USAGE, and RATIONALE sections of the dlsym() descripion on
P735-736, L24689-24748 with:

NAME
        dlsym -- get the address of a symbol from a symbol table handle

SYNOPSIS
        #include <dlfcn.h>
        void *dlsym(void *restrict handle, const char *restrict name);

DESCRIPTION
        The dlsym() function shall obtain the address of a symbol (a
        function identifier or a data object identifier) defined in the
        symbol table identified by the handle argument.  The handle
        argument is a symbol table handle returned from a call to
        dlopen() (and which has not since been released by a call to
        dlclose()), and name is the symbol's name as a character
        string.  The return value from dlsym(), cast to a pointer to the
        type of the named symbol, can be used to call (in the case of a
        function) or access the contents of (in the case of a data
        object) the named symbol.

        The dlsym() function shall search for the named symbol in
        the symbol table referenced by handle.  If the symbol table was
        created with lazy loading (see RTLD_LAZY in dlopen()), load
        ordering shall be used in dlsym() operations to relocate
        executable object files needed to resolve the symbol.  The
        symbol resolution algorithm used shall be dependency order
        as described in dlopen().

        The RTLD_DEFAULT and RTLD_NEXT symbolic constants (which may be
        defined in <dlfcn.h>) are reserved for future use as special
        values that applications may be allowed to use for handle.

RETURN VALUE
        Upon successful completion, if name names a function identifier,
        dlsym() shall return the address of the function converted from
        type pointer to function to type pointer to void; otherwise
        dlsym() shall return the address of the data object associated
        with the data object identfier named by name converted from a
        pointer to the type of the data object to a pointer to void.  If
        handle does not refer to a valid symbol table handle or if the
        symbol named by name cannot be found in the symbol table
    associated with handle, dlsym() shall return a null pointer.
    More detailed diagnostic information shall be available through
    dlerror().

ERRORS
        No errors are defined.

EXAMPLES
        The following example shows how dlopen() and dlsym() can be used
        to access either a function or a data object.  For simplicity,
        error checking has been omitted.

        void    *handle;
        int     (*fptr)(int),
                *iptr,
                result;

        /* open the needed symbol table */
        handle = dlopen("/usr/home/me/libfoo.so", RTLD_LOCAL | RTLD_LAZY);

        /* find the address of the function my_function */
        fptr = (int (*)(int))dlsym(handle, "my_function");

        /* find the address of the data object my_object */
        iptr = (int *)dlsym(handle, "my_OBJ");

        /* invoke my_function, passing the value of my_OBJ as the parameter */
        result = (*fptr)(*iptr);

APPLICATION USAGE
        The following special purpose values for handle are reserved for
        future use and have the indicated meanings:

        RTLD_DEFAULT    The identifier lookup happens in the normal
                        global scope; that is, a search for a identifier
                        using handle would find the same definition as a
                        direct use of this identifier in the program
                        code.

        RTLD_NEXT       Specifies the next executable object file after
                        this one that defines name.  This one refers to
                        the executable object file containing the
                        invocation of dlsym().  The next executable
                        object file is the one found upon the
                        application of a load order symbol resolution
                        algorithm (see dlopen()).  The next symbol is
                        either one of global scope (because it was
                        introduced as part of the original process image
                        or because it was added with a dlopen()
                        operation including the RTLD_GLOBAL flag), or is
                        in an executable object file that was included
                        in the same dlopen() operation that loaded this
                        one.

                        The RTLD_NEXT flag is useful to navigate an
                        intentionally created hierarchy of
                        multiply-defined symbols created through
                        interposition.  For example, if a program wished
                        to create an implementation of malloc() that
                        embedded some statistics gathering about memory
                        allocations, such an implementation could use
                        the real malloc() definition to perform the
                        memory allocation--and itself only embed the
                        necessary logic to implement the statistics
                        gathering function.

        Note that conversion from a void * pointer to a function pointer
        as in:

                fptr = (int (*)(int))dlsym(handle, "my_function");

        is not defined by the ISO C Standard.  This standard requires
        this conversion to work correctly on conforming implementations.

RATIONALE
        None.

------------------------------------------------------------------------


(0000210)
geoffclare (manager)
2009-08-28 09:02
edited on: 2009-08-30 02:28

When we progress this down the interpretations track, the accepted text
needs a couple of minor editorial changes:

Change "NULL pointer" to "null pointer".

Change "Similarly, note that once RTLD_GLOBAL has been specified"
to "If RTLD_GLOBAL has been specified".

August 8, 2009, 19:27 PDT:
Geoff is correct. These are editorial mistakes. These have been
fixed in place in Note: 0000205.

 - Don Cragun

(0000243)
Don Cragun (manager)
2009-09-28 00:25

Further corrections were added to Note: 0000205 reflecting changes discussed on
the austin-group-l alias. This discussion also led to the upcoming modification
to Austin Group Interpretation reference 1003.1-2001 #003.

- Issue History
Date Modified Username Field Change
2009-06-29 02:27 msbrown New Issue
2009-06-29 02:27 msbrown Status New => Under Review
2009-06-29 02:27 msbrown Assigned To => ajosey
2009-06-29 02:27 msbrown Name => Mark Brown
2009-06-29 02:27 msbrown Organization => IBM
2009-06-29 02:27 msbrown User Reference => Pointer
2009-06-29 02:27 msbrown Section => (section number or name, can be interface name)
2009-06-29 02:27 msbrown Page Number => 541
2009-06-29 02:27 msbrown Line Number => 18886
2009-06-29 02:27 msbrown Note Added: 0000129
2009-06-29 02:28 msbrown Final Accepted Text => Note: 0000129
2009-06-29 02:28 msbrown Status Under Review => Resolved
2009-06-29 02:28 msbrown Resolution Open => Accepted As Marked
2009-07-01 14:02 msbrown Name Mark Brown => Nick Stoughton
2009-07-01 14:02 msbrown Organization IBM =>
2009-07-01 14:02 msbrown Reporter msbrown => nick
2009-07-01 14:03 msbrown User Reference Pointer =>
2009-07-01 14:03 msbrown Section (section number or name, can be interface name) => Pointer
2009-07-07 07:23 Konrad_Schwarz Note Added: 0000155
2009-07-07 07:28 Konrad_Schwarz Note Edited: 0000155
2009-07-07 07:57 Konrad_Schwarz Note Edited: 0000155
2009-07-07 08:13 Konrad_Schwarz Note Edited: 0000155
2009-07-07 08:38 Konrad_Schwarz Note Added: 0000156
2009-08-20 21:18 Don Cragun Interp Status => ---
2009-08-20 21:18 Don Cragun Final Accepted Text Note: 0000129 =>
2009-08-20 21:18 Don Cragun Note Added: 0000203
2009-08-20 21:18 Don Cragun Resolution Accepted As Marked => Reopened
2009-08-20 21:19 Don Cragun Status Resolved => Under Review
2009-08-27 00:03 Don Cragun Note Added: 0000205
2009-08-27 00:14 Don Cragun Note Edited: 0000205
2009-08-27 16:45 Don Cragun Note Edited: 0000205
2009-08-27 16:46 Don Cragun Interp Status --- => Pending
2009-08-27 16:46 Don Cragun Final Accepted Text => Note: 0000205
2009-08-27 16:46 Don Cragun Status Under Review => Interpretation Required
2009-08-27 16:46 Don Cragun Resolution Reopened => Accepted As Marked
2009-08-28 09:02 geoffclare Note Added: 0000210
2009-08-30 02:24 Don Cragun Note Edited: 0000205
2009-08-30 02:28 Don Cragun Note Edited: 0000210
2009-08-30 02:28 Don Cragun Note Edited: 0000210
2009-09-17 15:41 nick Interp Status Pending => Proposed
2009-09-28 00:21 Don Cragun Note Edited: 0000205
2009-09-28 00:25 Don Cragun Note Added: 0000243
2009-09-28 09:01 Don Cragun Note Edited: 0000205
2009-09-28 16:33 nick Tag Attached: c99
2009-11-06 06:52 ajosey Note Edited: 0000205
2009-11-06 06:53 ajosey Interp Status Proposed => Approved
2009-11-12 16:47 msbrown Relationship added has duplicate 0000178
2010-09-20 09:15 geoffclare Tag Attached: tc1-2008
2013-04-16 13:06 ajosey Status Interpretation Required => Closed
2014-03-08 06:27 ajosey Relationship added related to 0000829
2021-01-04 10:50 geoffclare Relationship added related to 0001439
2021-10-14 15:47 rhansen Relationship added has duplicate 0000099
2021-10-14 15:48 rhansen Relationship added has duplicate 0000100
2023-03-23 16:42 geoffclare Relationship added related to 0001644


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker