Skip to content

Bug in reading UTF-16LE file?

7 messages · Tomas Kalibera, Jeff Newmiller, Matt Denwood

#
On 9/9/24 12:53, Tomas Kalibera wrote:
This is a problem in macOS libiconv. When converting from "UTF-16" with 
a BOM, it correctly learns the byte-order from the BOM, but later 
forgets it in some cases.? This is not a problem in R, but could be 
worked-around in R.

As Simon wrote, to avoid running into these problems (in released 
versions of R), one should use "UTF-16LE", so explicitly specify the 
byte-order in the encoding name. This is useful also because it is not 
clear what should be the default when no BOM is present and different 
systems have different defaults.

Best
Tomas
#
So, buggy system code on one system...
... leads to institutionalized non-complince.
This is nonsense, for reasons previously provided. You are calling a bug a feature. The BOM is supposed to prevent you from having to know this detail, and what you do when no BOM is present should have no bearing on this case.

If Apple is intransigent (which would not be out of character) you could avoid institutionalized non-compliance at the user level by recognizing the buggy system and replacing the generic specification with this inappropriate LE or BE specification as directed by the BOM in the Mac-specific R code.
On October 1, 2024 4:34:41 AM MST, Tomas Kalibera <tomas.kalibera at gmail.com> wrote:

  
    
#
On 10/1/24 15:31, Jeff Newmiller wrote:
I will try to explain this differently. The handling of BOMs in existing 
iconv implementations is unreliable (one issue is documented in R 
documentation, one issue is the one we have ran into now). Because it is 
unreliable, people who want to be defensive and avoid problems are 
advised to use *LE (or *BE) specifications. What is the default 
byte-order when no BOM is specified is not reliable, either (defaults 
differ between systems and the standard is open to interpretation - e.g. 
my Linux and Windows builds of R default to little-endian, while my 
macOS build defaults to big-endian). It is thus not advisable to depend 
on the default order, either, and a defensive solution is again to use 
*LE or *BE specifications. So, in principle, simply always use *LE or *BE.

This advice is not a feature, it is a work-around that works for two 
problems: that the byte order for specifications like "UTF-16" is 
unknown (bug in the standard) and that specifying the byte-order by a 
BOM is unreliable (bugs in implementations of iconv).
Yes, indeed, the work-around for the libiconv bug can be implemented in 
future versions of R and an experimental version is already in R-devel 
(still subject to change), so that at user level, specifying say 
"UTF-16" on an input with BOM will correctly use the byte-order of the BOM.

I don't find anything inappropriate about the *LE/*BE specifications.

Best
Tomas
#
That was not clear (to me?) in your previous summary. Thanks for clarifying.
The Unicode FAQ does. If you specify endian-ness and a BOM is present and these specifications agree then it would seem no harm no foul. The problem is that if they conflict, then there is no clearly correct behavior: if the BOM is valid then the user spec must be incorrectly specified and favoring the user specification forces incorrect decoding. If the BOM is erroneous, then you would want the user to be able to override the incorrect BOM... but these two cases amount to defeating the BOMs purpose... it might as well not be there. So the compliant handling of data with a BOM is for the user to make a standard practice of not specifying endianness _unless they must override an invalid BOM_ (which ought to be highly unusual)... save the sledgehammer for unusual cases, and let the BOM be the "only" specification if it is present. This lets the BOM serve its intended purpose of reducing how often users have to guess.
On October 1, 2024 1:50:25 PM MST, Tomas Kalibera <tomas.kalibera at gmail.com> wrote:

  
    
#
Hi Jeff / all
On 02/10/2024, 08.54, Jeff Newmiller wrote:
Actually, the Unicode FAQ (https://unicode.org/faq/utf_bom.html, under "Q: Why wouldn?t I always use a protocol that requires a BOM?") says:  "In particular, if a text data stream is marked as UTF-16BE, UTF-16LE, UTF-32BE or UTF-32LE, a BOM is neither necessary nor permitted. Any U+FEFF would be interpreted as a ZWNBSP."

So, my interpretation of the Unicode recommendation is that specifying *LE/*BE takes precedence - and if both are provided, then the BOM should be interpreted as a zero-width non-breaking space i.e. ignored.  Therefore, it would seem sensible for defensive programmers to specify *LE/*BE manually, safe in the knowledge that any BOM (correct or otherwise) becomes irrelevant - which is what I believe Tomas and Simon are suggesting.  Although it is possible I misunderstood something...

Best wishes,

Matt



?On 02/10/2024, 08.54, "R-SIG-Mac on behalf of Jeff Newmiller via R-SIG-Mac" <r-sig-mac-bounces at r-project.org <mailto:r-sig-mac-bounces at r-project.org> on behalf of r-sig-mac at r-project.org <mailto:r-sig-mac at r-project.org>> wrote:

[SNIP]

        
On October 1, 2024 1:50:25 PM MST, Tomas Kalibera <tomas.kalibera at gmail.com <mailto:tomas.kalibera at gmail.com>> wrote:

  
    
#
Prior to saying:
it says:
which ("neither ... permitted") says don't mix an endianness indicator in your encoding spec with a BOM. It makes sense to be able to override an incorrect BOM, but not to do it all the time because if you do the BOM is rendered toothless. Programmer mis-specification is the problem that the BOM exists to solve.
On October 2, 2024 2:04:45 AM MST, Matt Denwood <md at sund.ku.dk> wrote:

  
    
#
On 10/2/24 11:04, Matt Denwood wrote:
I think it is a valid concern what happens with a BOM on *LE and *BE 
input, and to be most defensive and conformant to Unicode FAQ, one would 
not use a BOM with these.

But R treats "UTF-16LE" specially, as documented in ?connections and 
cited earlier in this thread. UTF-16LE is meant to be used for Windows 
"Unicode" text files in R. As a work-around for some version of iconv 
that wouldn't accept a BOM (from a source code comment it is/was seen in 
glibc's iconv) in a UTF-16LE stream, R removes the BOM (if it is 
correctly encoded as little-endian) before passing it to iconv.

We might add some similar handling of less used combinations (UTF-32LE, 
UTF-32BE, UTF-16BE) to future versions of R. What already exists in R is 
removal of a BOM in readLines() - this would happen when the result is 
in UTF-8 - so if iconv lets it through, and it is read via readLines(), 
it won't be visible.

Tomas