NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/58136 (Use after free in libintl pgettext)



> On Aug 19, 2024, at 7:50 AM, gnats-admin%netbsd.org@localhost wrote:
> 
> The following reply was made to PR lib/58136; it has been noted by GNATS.
> 
> From: Paul Ripke <stix%stix.id.au@localhost>
> To: gnats-bugs%netbsd.org@localhost
> Cc: 
> Subject: Re: lib/58136 (Use after free in libintl pgettext)
> Date: Mon, 19 Aug 2024 21:45:04 +1000
> 
> From my reading of C's behaviour, dereferencing a freed pointer is undefined
> behaviour, obviously. But using the pointer value should not be? Indeed, when
> compiled with clang/llvm, your code results in only one call to free.

In N1256 (a C99 draft) section 6.2.4p2, it says

  The /lifetime/ of an object is the portion of program execution during which
  storage is guaranteed to be reserved for it. An object exists, has a constant
  address,^25) and retains its last-stored value throughout its lifetime.^26) If
  an object is referred to outside of its lifetime, the behavior is undefined. The
  value of a pointer becomes indeterminate when the object it points to
  reaches the end of its lifetime.

Section 7.20.3 describes the malloc, calloc, realloc, and free functions. Section
7.20.3p1 contains the sentence

  The lifetime of an allocated object extends from the allocation until the
  deallocation.

Section 3.17.2 defines "indeterminate value" as

  either an unspecified value or a trap representation

Section 3.17.3 defines "unspecified value" as

  valid value of the relevant type where this International Standard imposes
  no requirements on which value is chosen in any instance

  NOTE An unspecified value cannot be a trap representation

Putting this together, we can see that accessing the value of a pointer after
it has been freed can result in a meaningless value or a trap.

ANSI C says something slightly different. Section 6.1.2.4 of ANSI C says

    An object has a /storage duration/ that determines its lifetime. There are
  two storage durations: static and automatic.

    An object whose identifier is declared with external or internal linkage, or
  with the storage-class specifier static has /static storage duration/. For such
  an object, storage is reserved and its stored value is initialized only once,
  prior to program startup. The object exists and retains its last-stored value
  throughout the execution of the program.^15

    An object whose identifier is declared with no linkage and without the
  storage-class specifier static has /automatic storage duration/. Storage is
  guaranteed to be reserved for a new instance of such an object on each
  normal entry into the block with which it is associated, or on a jump from
  outside the block to a labeled statement in the block or in an enclosed
  block. In an initialization is specified for the value stored in the object, it is
  performed on each normal entry, but not if the block is entered by a jump
  to a labeled statement. Storage for the object is no longer guaranteed to
  be reserved when execution of a block ends in any way. (Entering an
  enclosed block suspends but does not end execution of the enclosing
  block. Calling a function suspends but does not end execution of the
  block containing the call.) The value of a pointer that referred to an object
  with automatic storage duration that is no longer guaranteed to be
  reserved is indeterminate.

Section 7.10.3 addresses malloc, calloc, realloc and free, and contains
the sentence

  The value of a pointer that refers to freed space is indeterminate.

Section 3.16 defines "undefined behavior" as

  Behavior, upon use of a nonportable or erroneous program construct,
  of erroneous data, or of indeterminately valued objects, for which this
  International Standard imposes no requirements. Permissible 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
  issuance of a diagnostic message), to terminating a translation or
  execution (with the issuance of a diagnostic message).

    If a "shall" or "shall not" requirement that appears outside of a constraint
  is violated, the behavior is undefined. Undefined behavior is otherwise
  indicated in this International Standard by the words "undefined behavior"
  or by the omission of any explicit definition of behavior. There is no
  difference in emphasis among these three; they all describe "behavior
  that is undefined."

Putting these together, we see that accessing a pointer after is has been freed is undefined behavior in ANSI C.

> Agreed on the missing test, though. This code is old and crufty, does it have
> any coverage at all? I didn't see any after a brief look.
> 
> -- 
> Paul Ripke
> "Great minds discuss ideas, average minds discuss events, small minds
>  discuss people."
> -- Disputed: Often attributed to Eleanor Roosevelt. 1948.
> 



Home | Main Index | Thread Index | Old Index