惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

David Baron's Weblog

Software engineering, responsibility, and ownership Software engineering, responsibility, and ownership David Baron's weblog: Security and Inequality Running animations on the compositor thread David Baron's weblog: Tying ecosystems through browsers David Baron's weblog: Payments on the Web Thoughts on migrating to a secure Web David Baron's weblog: The need for government David Baron's weblog: Priority of constituencies How browser developers should seek feedback from Web developers A possible approach to shorter release cycles David Baron's weblog: Fifteen years Why debug builds (and assertions) are important Ten years of the Mozilla Foundation Open licensing at the W3C Why adding compositing and blending to CSS is harder than it looks How you can help with removing -moz- prefixes Moving bug history out of the primary display of a bug report Eating dogfood and shipping software Specification style and the future of the Web The bug system I wish I had CSS border-image changes and unprefixing Improving font size readability on Firefox for Android David Baron's weblog: CSS Animations, part 2 Hue-preserving color inversion with SVG filters Changes to handling of @-moz-keyframes David Baron's weblog: window.matchMedia() David Baron's weblog: CSS Animations What does a blur radius mean? Crash analysis in the future David Baron's weblog: calc() David Baron's weblog: colorDepth David Baron's weblog: Hidden complexity in specifications The most important field in a bug report: the summary WOFF font format submitted to W3C David Baron's weblog: :-moz-any() selector grouping setTimeout with a shorter delay Faster repainting in SVG foreignObject David Baron's weblog: Distributed Extensibility David Baron's weblog: Broadening crash analysis Correlating crashes with binary extensions or plugins David Baron's weblog: ex-HTML Downloadable font formats for the Web Web Accessibility as a Political Movement David Baron's weblog: CSS priorities David Baron's weblog: Bug priorities David Baron's weblog: Semi-vacation Some new CSS features in Firefox 3 David Baron's weblog: New selectors David Baron's weblog: The age of bugs Seeking a good Linux distribution David Baron's weblog: Teaching to the test David Baron's weblog: March 2008 David Baron's weblog: February 2008 David Baron's weblog: January 2008 David Baron's weblog: October 2007 David Baron's weblog: September 2007 David Baron's weblog: August 2007 David Baron's weblog: June 2007 David Baron's weblog: April 2007 David Baron's weblog: March 2007 David Baron's weblog: January 2007 David Baron's weblog: September 2006 David Baron's weblog: August 2006 David Baron's weblog: July 2006 David Baron's weblog: May 2006 David Baron's weblog: February 2006 David Baron's weblog: January 2006 David Baron's weblog: December 2005 David Baron's weblog: October 2005 David Baron's weblog: September 2005 David Baron's weblog: June 2005 David Baron's weblog: May 2005 David Baron's weblog: April 2005 David Baron's weblog: March 2005 David Baron's weblog: February 2005 David Baron's weblog: October 2004 David Baron's weblog: September 2004 David Baron's weblog: August 2004 David Baron's weblog: June 2004 David Baron's weblog: May 2004 David Baron's weblog: April 2004 David Baron's weblog: March 2004 David Baron's weblog: February 2004 David Baron's weblog: January 2004 David Baron's weblog: November 2003 David Baron's weblog: October 2003 David Baron's weblog: September 2003 David Baron's weblog: August 2003 David Baron's weblog: July 2003 David Baron's weblog: June 2003 David Baron's weblog: May 2003 David Baron's weblog: April 2003 David Baron's weblog: March 2003 David Baron's weblog: February 2003 David Baron's weblog: January 2003 David Baron's weblog: December 2002 David Baron's weblog: November 2002 David Baron's weblog: September 2002
Beware of locale-specific behavior in the C library
David Baron · 2012-12-23 · via David Baron's Weblog

In the English speaking world, we write the decimal number for one and a half as "1.5", but in France, they write "1,5". When a programming environment is designing an interface, they could give that interface locale-independent behavior (so that a function writing a number to a string or reading a number from a string always writes or reads "1.5" only) or locale-specific behavior (so that such a function behaves differently depending on the system settings). This applies to much more than number formatting: for example, it also applies to things dealing with dates, translation of messages, or alphabetic sorting.

Programs often want locale-specific behavior when presenting data to the end user or receiving input from the end user. However, in file formats and network protocols, programs generally want locale-independent behavior so that files can be exchanged around the world and servers in different parts of the world can communicate.

The C programming language made what I consider a horrible design decision. Rather than having separate functions for locale-independent and locale-specific actions, C has a global function called setlocale to change the behavior of large sets of functions. It defaults to locale-independent behavior, but many applications such as Firefox choose to change it to the locale-specific behavior so they can get at the locale-specific behavior in some cases. (It's not clear to me what Firefox needs this for, though.) The setlocale function is global (and presumably not threadsafe); it changes the behavior of all threads. (There are platform-specific better ways (uselocale or _configthreadlocale, strtod_l or _strtod_l), but these don't appear to be easily portable.)

I think this global switch was a design mistake. Programs that spend a lot of time printing messages to users also deal with data formats or protocols that should be consistent across locales. And in programs that would like to be portable and would like to be fast don't want to use non-threadsafe function of unknown performance characteristics around every simple string operations. But programs like Firefox that want some locale-specific behavior end up switching into locale-specific mode and just staying there (though we actually have a bunch of code to call setlocale at various times, which is even scarier).

This creates what I think Henri would call an attractive nuisance. We have a constant stream of bugs (such as the bug that prompted me to write this) where code dealing with file formats or network protocols accidentally uses locale-specific functions, works correctly for the US-based developer, and doesn't work as it's supposed to somewhere else in the world.

In the Firefox codebase, our typical workaround for these bugs is to avoid the C library. We can use NSPR's functions (PR_smprintf, PR_strtod), which are locale-independent, instead of similar C library functions, or we can use other alternatives in our source tree, such as the double conversion library (in mfbt/double-conversion/ or one-off functions like nsCRT::atoll. But quick searches of our source tree show hundreds of potential bugs sitting there today that we haven't yet worked around. We need a better solution.

First, I wonder if we can switch to running in "C" locale (i.e., in C's default locale-independent mode). It's not clear to me what we get from changing the C library locale to the user's locale; most of our important localization behavior is implemented at a different level from the C library. This might require figuring out how to use the platform-specific APIs to get the information we need without changing global behavior for all threads.

Second, I think we should be running our unit tests in locales other than US English. We don't have to run a full matrix of tests (which is what such proposals always seem to get blocked on), but we could, say, run 32-bit Linux tests in French locale, 64-bit Linux tests in Japanese locale, etc., perhaps even replacing the current runs in US English locale.

Third, unless we can switch to locale-independent behavior quickly, we need better awareness that many functions from the C library can have locale-specific behavior: anything to do with date formatting, float and integer reading and writing, and string sorting. (I'm having trouble finding evidence of this behavior for integers, although glibc certainly has some #ifdef-ed code in its strtol implementation to parse locale-specific group separators (e.g., "1,000,000" for one million; see my test program). I think the vast majority of the problems we've had have dealt with reading and writing floats, though.