FreeRADIUS / freeradius-server

FreeRADIUS - A multi-protocol policy server.
http://freeradius.org
GNU General Public License v2.0
2.13k stars 1.08k forks source link

FreeRADIUS 3.0.8 can't log accounting info to mysql when using UTF-8 encoded Chinese SSID name in hostapd program #1021

Closed moontide closed 9 years ago

moontide commented 9 years ago

Update 2

I installed FreeRADIUS 3.0.8 (built for Fedora 22) in Fedora 21.

This bug seems still existed. The different between 3.0.4 & 3.0.8 when writing to radacct table is that calledstationid value is shorter, but it's still too long to save to MySQL database.

3.0.4 'D8-5D-4C-7A-CF-64:=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab =5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf =5C=5Cxe9=5C=5Cx94=5C=5Cx9f=5C=5Cxe6=5C=5Cx96=5C=5Cxa4=5C=5Cxe6=5C=5Cx8b=5C=5Cxb' (262 bytes)

3.0.8 'D8-5D-4C-7A-CF-64:=5Cxe7=5Cx83=5Cxab=5Cxe7=5Cx83=5Cxab=5Cxe7=5Cx83=5Cxab =5Cxe5=5Cxb1=5Cxaf=5Cxe5=5Cxb1=5Cxaf=5Cxe5=5Cxb1=5Cxaf =5Cxe9=5Cx94=5Cx9f=5Cxe6=5Cx96=5Cxa4=5Cxe6=5Cx8b=5Cxb' (181 bytes)

Update

Sorry, I didn't check doc/Changelog file of the latest version. I only search the issues here and not found a bug report about this.

I found this in doc/Changelog file according arr2036's comment. Since this bug had been closed and locked, I'll updated it here (in case other users may encountered similar issue).

FreeRADIUS 3.0.5 Fri 21 Nov 2014 15:30:00 EDT urgency=medium
Bug fixes
...
* Don't escape UTF8 chars in SQL query strings.
...

Guess I need to wait for the release of Fedora 22 in several days. The newest version of FreeRADIUS in Fedora 21 is still 3.0.4.

Description

I'm creating a WiFi software AP with WPA2-Enterprise/RADIUS auth type.The SSID name in hostapd.conf is set to '烫烫烫 屯屯屯 锟斤拷' (UTF-8 encoding, so it's length should be 29(3*9+2) bytes).

The Called-Station-Id information received/logged by FreeRADIUS is 'D8-5D-4C-7A-CF-64:\\xe7\\x83\\xab\\xe7\\x83\\xab\\xe7\\x83\\xab \\xe5\\xb1\\xaf\\xe5\\xb1\\xaf\\xe5\\xb1\\xaf \\xe9\\x94\\x9f\\xe6\\x96\\xa4\\xe6\\x8b\\xb'. (the last byte should be '\\xb7', i don't know why 7 is missed here)

The calledstationid column value in INSERT sql statement is quoted-printable encoded string of Called-Station-Id: 'D8-5D-4C-7A-CF-64:=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab =5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf =5C=5Cxe9=5C=5Cx94=5C=5Cx9f=5C=5Cxe6=5C=5Cx96=5C=5Cxa4=5C=5Cxe6=5C=5Cx8b=5C=5Cxb', which is too long (262 bytes) for varchar(50) datatype: Data too long for column 'calledstationid' at row 1'

I know I can change the data type of calledstationid to a longer data type as a workaround, but I'd like log the calledstationid using it's raw bytes code (which means 烫烫烫 屯屯屯 锟斤拷 string in UTF-8 encoding) rather than a quoted-printable encoded string.

My environment (all running in 1 pc):

(13) Received Accounting-Request Id 71 from 127.0.0.1:35433 to 127.0.0.1:1813 length 286
(13)   Acct-Multi-Session-Id = '556567D6+00000002'
(13)   Acct-Status-Type = Start
(13)   Acct-Authentic = RADIUS
(13)   User-Name = 'MY_USER_NAME'
(13)   NAS-IP-Address = 127.0.0.1
(13)   Called-Station-Id = 'D8-5D-4C-7A-CF-64:\\xe7\\x83\\xab\\xe7\\x83\\xab\\xe7\\x83\\xab \\xe5\\xb1\\xaf\\xe5\\xb1\\xaf\\xe5\\xb1\\xaf \\xe9\\x94\\x9f\\xe6\\x96\\xa4\\xe6\\x8b\\xb'
(13)   NAS-Port-Type = Wireless-802.11
(13)   NAS-Port = 1
(13)   Calling-Station-Id = '6C-71-D9-51-36-5D'
(13)   Connect-Info = 'CONNECT 54Mbps 802.11g'
(13)   Acct-Session-Id = '556567D6-00000002'
(13)   WLAN-Pairwise-Cipher = 1027076
(13)   WLAN-Group-Cipher = 1027076
(13)   WLAN-AKM-Suite = 1027073
(13) # Executing section preacct from file /etc/raddb/sites-enabled/default
(13)   preacct {
(13)     [preprocess] = ok
(13)     policy acct_unique {
(13)       if ("%{string:Class}" =~ /ai:([0-9a-f]{32})/i) {
(13)       EXPAND %{string:Class}
(13)          --> 
(13)       if ("%{string:Class}" =~ /ai:([0-9a-f]{32})/i)  -> FALSE
(13)       else {
(13)         update request {
(13)           EXPAND %{md5:%{User-Name},%{Acct-Session-ID},%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port}}
(13)              --> 5a4510df36b50f2d6335a0a565aa74eb
(13)           &Acct-Unique-Session-Id := 5a4510df36b50f2d6335a0a565aa74eb
(13)         } # update request = noop
(13)       } # else = noop
(13)     } # policy acct_unique = noop
(13) suffix: Checking for suffix after "@"
(13) suffix: No '@' in User-Name = "MY_USER_NAME", looking up realm NULL
(13) suffix: No such realm "NULL"
(13)     [suffix] = noop
(13)     [files] = noop
(13)   } # preacct = ok
(13) # Executing section accounting from file /etc/raddb/sites-enabled/default
(13)   accounting {
(13) detail: EXPAND /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d
(13) detail:    --> /var/log/radius/radacct/127.0.0.1/detail-20150527
(13) detail: /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d expands to /var/log/radius/radacct/127.0.0.1/detail-20150527
(13) detail: EXPAND %t
(13) detail:    --> Wed May 27 18:21:21 2015
(13)     [detail] = ok
(13)     [unix] = ok
(13) sql: EXPAND %{tolower:type.%{Acct-Status-Type}.query}
(13) sql:    --> type.start.query
(13) sql: Using query template 'query'
rlm_sql (sql): Reserved connection (7)
(13) sql: EXPAND %{User-Name}
(13) sql:    --> MY_USER_NAME
(13) sql: SQL-User-Name set to 'MY_USER_NAME'
(13) sql: EXPAND INSERT INTO radacct (acctsessionid,        acctuniqueid,       username, realm,            nasipaddress,       nasportid, nasporttype,     acctstarttime,      acctupdatetime, acctstoptime,       acctsessiontime,    acctauthentic, connectinfo_start,   connectinfo_stop,   acctinputoctets, acctoutputoctets,  calledstationid,    callingstationid, acctterminatecause,   servicetype,        framedprotocol, framedipaddress) VALUES ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', FROM_UNIXTIME(%{integer:Event-Timestamp}), FROM_UNIXTIME(%{integer:Event-Timestamp}), NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}')
(13) sql:    --> INSERT INTO radacct (acctsessionid,        acctuniqueid,       username, realm,            nasipaddress,       nasportid, nasporttype,     acctstarttime,      acctupdatetime, acctstoptime,       acctsessiontime,    acctauthentic, connectinfo_start,   connectinfo_stop,   acctinputoctets, acctoutputoctets,  calledstationid,    callingstationid, acctterminatecause,   servicetype,        framedprotocol, framedipaddress) VALUES ('556567D6-00000002', '5a4510df36b50f2d6335a0a565aa74eb', 'MY_USER_NAME', '', '127.0.0.1', '1', 'Wireless-802.11', FROM_UNIXTIME(1432722081), FROM_UNIXTIME(1432722081), NULL, '0', 'RADIUS', 'CONNECT 54Mbps 802.11g', '', '0', '0', 'D8-5D-4C-7A-CF-64:=5Cxe7=5Cx83=5Cxab=5Cxe7=5Cx83=5Cxab=5Cxe7=5Cx83=5Cxab =5Cxe5=5Cxb1=5Cxaf=5Cxe5=5Cxb1=5Cxaf=5Cxe5=5Cxb1=5Cxaf =5Cxe9=5Cx94=5Cx9f=5Cxe6=5Cx96=5Cxa4=5Cxe6=5Cx8b=5Cxb', '6C-71-D9-51-36-5D', '', '', '', '')
(13) sql: Executing query: INSERT INTO radacct (acctsessionid,      acctuniqueid,       username, realm,            nasipaddress,       nasportid, nasporttype,     acctstarttime,      acctupdatetime, acctstoptime,       acctsessiontime,    acctauthentic, connectinfo_start,   connectinfo_stop,   acctinputoctets, acctoutputoctets,  calledstationid,    callingstationid, acctterminatecause,   servicetype,        framedprotocol, framedipaddress) VALUES ('556567D6-00000002', '5a4510df36b50f2d6335a0a565aa74eb', 'MY_USER_NAME', '', '127.0.0.1', '1', 'Wireless-802.11', FROM_UNIXTIME(1432722081), FROM_UNIXTIME(1432722081), NULL, '0', 'RADIUS', 'CONNECT 54Mbps 802.11g', '', '0', '0', 'D8-5D-4C-7A-CF-64:=5Cxe7=5Cx83=5Cxab=5Cxe7=5Cx83=5Cxab=5Cxe7=5Cx83=5Cxab =5Cxe5=5Cxb1=5Cxaf=5Cxe5=5Cxb1=5Cxaf=5Cxe5=5Cxb1=5Cxaf =5Cxe9=5Cx94=5Cx9f=5Cxe6=5Cx96=5Cxa4=5Cxe6=5Cx8b=5Cxb', '6C-71-D9-51-36-5D', '', '', '', '')
(13) sql: ERROR: rlm_sql_mysql: ERROR 1406 (Data too long for column 'calledstationid' at row 1): 22001
(13) sql: SQL query returned: server error
rlm_sql (sql): Released connection (7)
(13)     [sql] = fail
(13)   } # accounting = fail
(13) Not sending reply to client.
(13) Finished request
(13) <done>: Cleaning up request packet ID 71 with timestamp +585

Full log (3.0.4):

Note: I have replaced my User-Name to MY_USER_NAME.

(90) Received Accounting-Request packet from host 127.0.0.1 port 51985, id=89, length=328
(90)    Acct-Multi-Session-Id = '5562C8B8+00000001'
(90)    Acct-Status-Type = Stop
(90)    Acct-Authentic = RADIUS
(90)    User-Name = 'MY_USER_NAME'
(90)    NAS-IP-Address = 127.0.0.1
(90)    Called-Station-Id = 'D8-5D-4C-7A-CF-64:\\xe7\\x83\\xab\\xe7\\x83\\xab\\xe7\\x83\\xab \\xe5\\xb1\\xaf\\xe5\\xb1\\xaf\\xe5\\xb1\\xaf \\xe9\\x94\\x9f\\xe6\\x96\\xa4\\xe6\\x8b\\xb'
(90)    NAS-Port-Type = Wireless-802.11
(90)    NAS-Port = 2
(90)    Calling-Station-Id = '40-4D-8E-68-20-67'
(90)    Connect-Info = 'CONNECT 54Mbps 802.11g'
(90)    Acct-Session-Id = '5562C8B8-00000001'
(90)    WLAN-Pairwise-Cipher = 1027076
(90)    WLAN-Group-Cipher = 1027076
(90)    WLAN-AKM-Suite = 1027073
(90)    Acct-Session-Time = 4870
(90)    Acct-Input-Packets = 2735
(90)    Acct-Output-Packets = 883
(90)    Acct-Input-Octets = 327115
(90)    Acct-Output-Octets = 346720
(90)    Event-Timestamp = 'May 25 2015 16:24:20 CST'
(90)    Acct-Terminate-Cause = User-Request
(90) # Executing section preacct from file /etc/raddb/sites-enabled/default
(90)   preacct {
(90)   [preprocess] = ok
(90)   acct_unique acct_unique {
(90)     if ("%{string:Class}" =~ /ai:([0-9a-f]{32})/i)
(90) EXPAND %{string:Class}
(90)    -->
(90)     if ("%{string:Class}" =~ /ai:([0-9a-f]{32})/i)  -> FALSE
(90)    else else {
(90)     update request {
(90) EXPAND %{md5:%{User-Name},%{Acct-Session-ID},%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port}}
(90)    --> 3aac24a738e0b51db7d06e7562457e52
(90)    Acct-Unique-Session-Id := "3aac24a738e0b51db7d06e7562457e52"
(90)     } # update request = noop
(90)    } # else else = noop
(90)   } # acct_unique acct_unique = noop
(90)  suffix : Checking for suffix after "@"
(90)  suffix : No '@' in User-Name = "MY_USER_NAME", looking up realm NULL
(90)  suffix : No such realm "NULL"
(90)   [suffix] = noop
(90)   [files] = noop
(90)  } #  preacct = ok
(90) # Executing section accounting from file /etc/raddb/sites-enabled/default
(90)   accounting {
(90)  detail : EXPAND /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d
(90)  detail :    --> /var/log/radius/radacct/127.0.0.1/detail-20150525
(90)  detail : /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d expands to /var/log/radius/radacct/127.0.0.1/detail-20150525
(90)  detail : EXPAND %t
(90)  detail :    --> Mon May 25 16:24:20 2015
(90)   [detail] = ok
(90)   [unix] = ok
(90)  sql : EXPAND %{tolower:type.%{Acct-Status-Type}.query}
(90)  sql :    --> type.stop.query
(90)  sql : Using query template 'query'
rlm_sql (sql): Reserved connection (15)
(90)  sql : EXPAND %{User-Name}
(90)  sql :    --> MY_USER_NAME
(90)  sql : SQL-User-Name set to 'MY_USER_NAME'
(90)  sql : EXPAND UPDATE radacct SET acctstoptime  = FROM_UNIXTIME(%{integer:Event-Timestamp}), acctsessiontime    = '%{Acct-Session-Time}', acctinputoctets   = '%{%{Acct-Input-Gigawords}:-0}' << 32 | '%{%{Acct-Input-Octets}:-0}', acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' << 32 | '%{%{Acct-Output-Octets}:-0}', acctterminatecause = '%{Acct-Terminate-Cause}', connectinfo_stop = '%{Connect-Info}' WHERE acctsessionid     = '%{Acct-Session-Id}' AND username = '%{SQL-User-Name}' AND nasipaddress   = '%{NAS-IP-Address}'
(90)  sql :    --> UPDATE radacct SET acctstoptime  = FROM_UNIXTIME(1432542260), acctsessiontime    = '4870', acctinputoctets   = '0' << 32 | '327115', acctoutputoctets = '0' << 32 | '346720', acctterminatecause = 'User-Request', connectinfo_stop = 'CONNECT 54Mbps 802.11g' WHERE acctsessionid   = '5562C8B8-00000001' AND username      = 'MY_USER_NAME' AND nasipaddress   = '127.0.0.1'
rlm_sql (sql): Executing query: 'UPDATE radacct SET acctstoptime    = FROM_UNIXTIME(1432542260), acctsessiontime    = '4870', acctinputoctets   = '0' << 32 | '327115', acctoutputoctets = '0' << 32 | '346720', acctterminatecause = 'User-Request', connectinfo_stop = 'CONNECT 54Mbps 802.11g' WHERE acctsessionid   = '5562C8B8-00000001' AND username      = 'MY_USER_NAME' AND nasipaddress   = '127.0.0.1''
rlm_sql_mysql: Rows matched: 0  Changed: 0  Warnings: 0
(90)  sql : No records updated
(90)  sql : Trying next query...
(90)  sql : EXPAND INSERT INTO radacct (acctsessionid,      acctuniqueid,       username, realm,            nasipaddress,       nasportid, nasporttype,     acctstarttime,      acctupdatetime, acctstoptime,       acctsessiontime,    acctauthentic, connectinfo_start,   connectinfo_stop,   acctinputoctets, acctoutputoctets,  calledstationid,    callingstationid, acctterminatecause,   servicetype,        framedprotocol, framedipaddress) VALUES ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', FROM_UNIXTIME(%{integer:Event-Timestamp} - %{%{Acct-Session-Time}:-0}), FROM_UNIXTIME(%{integer:Event-Timestamp}), FROM_UNIXTIME(%{integer:Event-Timestamp}), '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{%{Acct-Input-Gigawords}:-0}' << 32 | '%{%{Acct-Input-Octets}:-0}', '%{%{Acct-Output-Gigawords}:-0}' << 32 | '%{%{Acct-Output-Octets}:-0}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}')
(90)  sql :    --> INSERT INTO radacct (acctsessionid,      acctuniqueid,       username, realm,            nasipaddress,       nasportid, nasporttype,     acctstarttime,      acctupdatetime, acctstoptime,       acctsessiontime,    acctauthentic, connectinfo_start,   connectinfo_stop,   acctinputoctets, acctoutputoctets,  calledstationid,    callingstationid, acctterminatecause,   servicetype,        framedprotocol, framedipaddress) VALUES ('5562C8B8-00000001', '3aac24a738e0b51db7d06e7562457e52', 'MY_USER_NAME', '', '127.0.0.1', '2', 'Wireless-802.11', FROM_UNIXTIME(1432542260 - 4870), FROM_UNIXTIME(1432542260), FROM_UNIXTIME(1432542260), '4870', 'RADIUS', '', 'CONNECT 54Mbps 802.11g', '0' << 32 | '327115', '0' << 32 | '346720', 'D8-5D-4C-7A-CF-64:=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab =5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf =5C=5Cxe9=5C=5Cx94=5C=5Cx9f=5C=5Cxe6=5C=5Cx96=5C=5Cxa4=5C=5Cxe6=5C=5Cx8b=5C=5Cxb', '40-4D-8E-68-20-67', 'User-Request', '', '', '')
rlm_sql (sql): Executing query: 'INSERT INTO radacct (acctsessionid,        acctuniqueid,       username, realm,            nasipaddress,nasportid, nasporttype,        acctstarttime,      acctupdatetime, acctstoptime,       acctsessiontime,    acctauthentic, connectinfo_start,   connectinfo_stop,   acctinputoctets, acctoutputoctets,  calledstationid,    callingstationid, acctterminatecause,   servicetype,        framedprotocol, framedipaddress) VALUES ('5562C8B8-00000001', '3aac24a738e0b51db7d06e7562457e52', 'MY_USER_NAME', '', '127.0.0.1', '2', 'Wireless-802.11', FROM_UNIXTIME(1432542260 - 4870), FROM_UNIXTIME(1432542260), FROM_UNIXTIME(1432542260), '4870', 'RADIUS', '', 'CONNECT 54Mbps 802.11g', '0' << 32 | '327115', '0' << 32 | '346720', 'D8-5D-4C-7A-CF-64:=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab=5C=5Cxe7=5C=5Cx83=5C=5Cxab =5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf=5C=5Cxe5=5C=5Cxb1=5C=5Cxaf =5C=5Cxe9=5C=5Cx94=5C=5Cx9f=5C=5Cxe6=5C=5Cx96=5C=5Cxa4=5C=5Cxe6=5C=5Cx8b=5C=5Cxb', '40-4D-8E-68-20-67', 'User-Request', '', '', '')'
rlm_sql_mysql: MYSQL check_error: 1406 received
rlm_sql (sql): Data too long for column 'calledstationid' at row 1
rlm_sql_mysql: MYSQL check_error: 1406 received
rlm_sql_mysql: Cannot store result
rlm_sql_mysql: MySQL error 'Data too long for column 'calledstationid' at row 1'
(90)  sql : No additional queries configured
rlm_sql (sql): Released connection (15)
rlm_sql (sql): 0 of 3 connections in use.  Need more spares
rlm_sql (sql): Opening additional connection (16)
rlm_sql_mysql: Starting connect to MySQL server
rlm_sql (sql): Closing connection (14): Hit idle_timeout, was idle for 629 seconds
rlm_sql (sql): You probably need to lower "min"
rlm_sql_mysql: Socket destructor called, closing socket
rlm_sql (sql): Closing connection (13): Hit idle_timeout, was idle for 633 seconds
rlm_sql (sql): You probably need to lower "min"
rlm_sql_mysql: Socket destructor called, closing socket
(90)   [sql] = noop
(90)   [exec] = noop
(90)  attr_filter.accounting_response : EXPAND %{User-Name}
(90)  attr_filter.accounting_response :    --> MY_USER_NAME
(90)  attr_filter.accounting_response : Matched entry DEFAULT at line 12
(90)   [attr_filter.accounting_response] = updated
(90)  } #  accounting = updated
(90) Sending Accounting-Response packet to host 127.0.0.1 port 51985, id=89, length=0
Sending Accounting-Response Id 89 from 127.0.0.1:1813 to 127.0.0.1:51985
(90) Finished request
Waking up in 0.3 seconds.
(90) Cleaning up request packet ID 89 with timestamp +4999

About the SSID name

These 3 set of characters are 3 set famous malformed characters in GBK character encoding, see http://blog.csdn.net/jarelzhou/article/details/19013037 (Chinese) for details.

The first two ( & ) comes from Visual C++ when debugging applications. Newly allocated memory in Visual C++ are all filled by 0xCC 0xCC... or 0xCD 0xCD..., which these bytes are 烫烫烫(HOT HOT HOT)... and 屯屯屯(collect/stock/station/village, but it sounds like 臀臀臀 which means BUTT BUTT BUTT)... in Simplifed Chinese Windows system (GBK encoding).

The last one had been described in wikipedia http://en.wikipedia.org/wiki/Specials_%28Unicode_block%29#Replacement_character . But in Simplified Chinese Windows system, when decoding 2 (or any even number) replacement character bytes (which is UTF-8 encoded: 0xEF 0xBF 0xBD, 0xEF 0xBF 0xBD) in GBK encoding (0xEF 0xBF, 0xBD 0xEF, 0xBF 0xBD), 锟斤拷 occurs!

arr2036 commented 9 years ago

If you'd bothered to check the release notes, you'd of seen this has already been fixed in a later version.