Standards state a contract or implication: *if* you, the developer follow 
_these_ rules, *then* the standardized item will follow _these_other_ 
rules (if compliant).  If you violate the implication, then the standard 
no longer applies and you have lost the guarantees of the standard.

_If_ you build an electrical plug with prongs of a certain composition, 
shape, size, and distance apart and nothing projecting out of a described 
volume, _then_ it will fit into this standard plug with sufficient contact 
to carry a particular current and resist physical force to move/remove it 
of some size.  If you go make the prongs of the wrong shape or size, then 
the rules are off and it might fail in many different ways: wrong shape or 
size?  Might not make contact enough to carry the standard current, or 
might not resist being removed sufficiently.  Too close together?  Might 
not fit at all or might break when inserted. etc.


In the case of POSIX, there's a long intro which (tries to) set out the 
rules that you have to follow.  Some of these are effectively compile-time 
restrictions (e.g., you MUST NOT define macros, variables, or functions 
with various names) and others which are effectively run-time restrictions 
(e.g., for many functions, particular arguments MUST be valid C strings).  
If you go outside those then, again, the rules are off.  If you put 
"#define struct union" before "#include <time.h>", or pass a NULL pointer 
as the first argument to gettimeofday(2) then you've violated the 
application side of the POSIX contract and the system is not required to 
do anything in particular.


Yes, standards can be written to require graceful degradation, effectively 
saying "if you don't follow _all_ the rules but did follow at least this 
shorter list, then the standardized item must still keep up part of its 
side."  This is common in security/safety standards.  In POSIX this shows 
up in some interfaces being required to return EINVAL or similar in 
certain cases...but POSIX DOES NOT specify every possible error case and 
explicitly leaves many such cases undefined, leaving it to applications to 
do whatever meets their goal, be it speed, simplicity, debugability, etc.


So, background having been set:

On Sat, 2 Dec 2017, Scott Cheloha wrote:
> TL;DR: POSIX.1-2008 says gettimeofday(2) can't return anything but 0,
> but we return -1 on invalid input.  We claim that our gettimeofday(2)
> conforms to POSIX.1-2008.  Is something off here?

Nope.  What POSIX says is that *if you follow the POSIX rules*, then 
gettimeofday() will only return zero.  It's perfectly acceptable for a 
particular implementation to document its own behavior above and beyond 
what the standard requires.  We happen to document that if you pass a 
bogus pointer to gettimeofday(2), something not permitted by POSIX, then 
it'll fail with error EFAULT.


EFAULT is kinda interesting in that POSIX documents its existence but does 
not require it to ever be returned.  Here's what POSIX says normatively:
  [EFAULT]
      Bad address. The system detected an invalid address in attempting to
      use an argument of a call. The reliable detection of this error
      cannot be guaranteed, and when not detected may result in the
      generation of a signal, indicating an address volation, which is
      sent to the process.

_Informatively_ (no compliance requirement!) it says this in the 
rationale:
  POSIX.1 requires (in the ERRORS sections of function descriptions)
  certain error values to be set in certain conditions because many
  existing applications depend on them.  Some error numbers, such
  as [EFAULT], are entirely implementation-defined and are noted
  as such in their description in the ERRORS section. This section
  otherwise allows wide latitude to the implementation in handling
  error reporting.
...
  [EFAULT]  Most historical implementations do not catch an error
            and set errno when an invalid address is given to the
            functions wait(), time(), or times(). Some implementations
            cannot reliably detect an invalid address. And most
            systems that detect invalid addresses will do so only
            for a system call, not for a library routine.


...
> Does this make our implementation non-conforming and does something
> in the manpage need to change?
>
> I do note that gettimeofday(2) predates [3] POSIX (and me :p), so
> perhaps this is just an ancient compromise between BSD and the
> standards committees?

It's not so much a compromise as the standards committee making a decision 
about where to draw the line of covered-vs-not.  In theory, a standard 
could be written that exactly described all the error cases...but it would 
take forever to write and resolve the ambiguities in the description and 
no implementation would ever comply with all the details.  And what would 
the benefit be?  We don't _want_ application authors to use those corners! 
So, since it doesn't seem to be useful to specify the behavior of 
gettimeofday() when you pass NULL, POSIX says "nope, out of bounds".


Philip Guenther

Reply via email to