tech@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: Ingo Schwarze <schwarze@usta.de>
To: tech@mdocml.bsd.lv
Cc: Thomas Klausner <wiz@NetBSD.org>
Subject: enum type safety
Date: Sun, 17 Aug 2014 17:57:46 +0200	[thread overview]
Message-ID: <20140817155745.GA3959@iris.usta.de> (raw)
In-Reply-To: <20140817122227.GH21604@danbala.tuwien.ac.at>

Hi,

Thomas Klausner just pointed out that some compilers still worry
that the local variable r might be used uninitialized in term_ascii.c,
function ascii_hspan().

Digging into this, i found that it cannot actually happen:

 1. The function ascii_hspan() is only called through the
    struct termp hspan function pointer.

 2. Such a call happens at exactly one place: term.c, term_hspan().

 3. The function term_hspan() has the following callers:

     - term.c, term_setwidth()
     - man_term.c, a2width()
     - mdoc_term.c, a2width()
     - mdoc_term.c, a2offs()

    All these callers initialize the struct roffsu passed to term_hspan()
    using a2roffsu() and checking the return value or SCALE_HS_INIT().

Now obviously, when compiling the term_ascii.c translation unit,
the compiler cannot know what the calling translation units may
pass into this non-static function.

But what can they?  All the enum roffscale enumeration constants
defined in out.h are handled in ascii_hspan().  Isn't that safe?
What could possibly go wrong?

Digging into this, i learnt something about C i didn't yet know.
Here is what the C standard says (C99 = ISO/IEC 9899:TC3,
C11 = ISO/IEC 9899:201x Comittee Draft):

 * Each enumerated type shall be compatible with a char,
   a signed integer type, or an unsigned integer type.
   The choice of type is implementation-defined, ...
   (C99/C11 6.7.2.2 paragraph 4)

 * Conversion of an operand value to a compatible type
   causes no change to the value or the representation.
   (C99/C11 6.3 paragraph 2)

So the C standard *requires* enum types to *not* be type-safe,
the following would be legal C:

	enum roffscale	 scale;
	char		 c;
	/* ... */
	scale = 42;
	/* ... */
	c = scale;

And now the C standard *requires* that c ends up being 42.

This is amazing.  You use enum for type safety (that's generally
regarded as good practice, isn't it?) and then the very standard
forbids the compiler to actually implement enum in a type-safe way.

So whereever you have an interface with external linkage accepting
an enum value, for defensive programming you have to assume that
*any* value representable in *any* signed or unsigned integer type
can come in, so you basically *always* need a default: clause.

Is this analysis right, or do you consider the patch appended
below as silly?

Yours,
  Ingo


Index: term_ascii.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/term_ascii.c,v
retrieving revision 1.31
diff -u -p -r1.31 term_ascii.c
--- term_ascii.c	16 Aug 2014 19:00:01 -0000	1.31
+++ term_ascii.c	17 Aug 2014 15:54:48 -0000
@@ -253,7 +253,7 @@ ascii_hspan(const struct termp *p, const
 	case SCALE_EM:
 		r = su->scale;
 		break;
-	case SCALE_MAX:
+	default:
 		abort();
 		/* NOTREACHED */
 	}
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

           reply	other threads:[~2014-08-17 15:58 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <20140817122227.GH21604@danbala.tuwien.ac.at>]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140817155745.GA3959@iris.usta.de \
    --to=schwarze@usta.de \
    --cc=tech@mdocml.bsd.lv \
    --cc=wiz@NetBSD.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).