Wandering Thoughts archives

2011-11-17

The drawback of modern X font handling

In some ways, font handling in modern versions of X is quite nice. We have a decent number of good, high quality fonts in modern scalable formats like TrueType, and one can use fonts from Windows and Mac OS X if one wants to. Thanks to various reforms in font handling, specifying fonts is generally easier and more flexible (hands up everyone who ever tried to generate or read an XLFD string for a particular font), and you can install personal fonts without huge contortions. But it does have one drawback, at least for someone like me.

In the old days of X font handling, the X server did all of the work. X clients simply told the server to render some text in a particular font; it was the server itself that was responsible for generating the font bitmaps and drawing them (sometimes the X server delegated generating font bitmaps to a separate program, such as xfs, the X font server). This meant that you only had to tune fonts in one place and your tuning applied to every X client that you ran, no matter what they were or where they running. Or to put it another way, I could carefully select an xterm font (and size) that I really liked and it would stick everywhere.

(The fly in this 'all in the server' ointment was default X application resources, but you could fix that with some more work.)

In the new world of X fonts, fonts are rendered separately by each X client (using various layers of font selection and rendering) and sent to the server as precomputed bitmaps. If all of your clients are running on the same machine and using the same set of font libraries, the result is the same as in the old world. But if some of your clients are running on different machines and displaying remotely (or some of your local clients have decided to use their own copies of libraries), they can render the same nominal font quite differently. This is especially so if you use generic font names like 'monospace' or 'serif', because what actual fonts those generic names map to is system-specific; one machine may very well map 'monospace' to 'DejaVu Sans Mono', while another maps it to 'Liberation Mono'.

(The corollary to this is that font availability is also a per-machine thing. If you install a new font you like onto your local workstation, an xterm or Firefox or whatever running from a remote server cannot use it.)

In the new world, what you see for something like 'DejaVu Sans Mono 10' depends on the specific version of the font each system has installed, what exact rendering library version each system is using, and what rendering settings each system is using for things like subpixel anti-aliasing. This drastically complicates efforts to, say, pick a single modern font for all of your terminal windows.

(I'm aware that the modern answer to this drawback is that I should run all of my X programs locally and just use ssh. This is what you could politely call a fail.)

Sidebar: a concrete example

Both of the following images are xterm using DejaVu Sans Mono 10, displaying on a Fedora 15 machine's X server. One of the xterms is running locally on the Fedora 15 machine; the other is running on a 32-bit Ubuntu 10.04 machine.

Fedora 15 xterm Ubuntu 10.04 xterm

One of these I rather like, one of these I can't stand.

(Part of the difference is clearly in different settings for subpixel anti-aliasing; the Ubuntu 10.04 version has colour fringes that the Fedora 15 version does not. But I don't think the difference in line width that makes the 10.04 version visibly blacker is due to that.)

unix/ModernXFontDrawback written at 17:22:18; Add Comment

A classic and standard C quoting bug

I recently read Evan Martin's entry on quoting and escaping, which brought to mind one of those classic C and Unix programming mistakes which hopefully is not done very much any more.

Suppose that ustr is a string that comes from user input. The classic form of this particular quoting bug is to write printf(ustr) (or perhaps fprintf(out, ustr)); a much obvious version of this is syslog(pri, ustr).

(Some people might think that the printf() version is silly since there are much more nominally efficient ways to print plain strings, but in practice plenty of people find it much more efficient on programmer time to use printf() or fprintf() to output everything.)

The problem with all of these is that the first argument to printf() and syslog() is not a plain string to be printed; it is a format. Like many quoting bugs, this goes undetected for much of the time because a true plain string is also a valid format that formats to itself. However, if someone supplies a 'plain string' that includes printf formatting directives, things rapidly go off the rails; if you are lucky the program crashes right away so you can immediately notice the problem.

(If you are sufficiently unlucky, this is an exploitable security vulnerability. And yes, people have written code like this that made it into important programs.)

The right solution is of course to quote the user supplied string. The simple way to do this is to supply your own simple formatting string: syslog(pri, "%s", ustr) (or the equivalent with printf() et al). Of course at this point you might want to think about other bad characters that could appear in ustr and how you want to display the message to make it clear that the string comes from the user, not from your program's internals.

This bug can happen with any function that takes a format string as an argument and in any language, not just C. C is just a more dangerous language to have it happen in because C generally has no check for the wrong number of arguments being supplied to a function.

(I have opinions on how languages can avoid this entire class of bugs, but that's something for another entry.)

(Perhaps this is not strictly a quoting bug. It is in my mind, but I may have a somewhat odd view of what constitutes one.)

programming/ClassicCQuotingBug written at 00:39:57; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.