[AMG]: This page exists as a temporary repository for a file that the SourceForge bug tracker won't let me attach. Will some SF administrator please file a way to get the file into the bug tracker, then delete this page? Thanks. The bug URL is: [https://sourceforge.net/tracker/index.php?func=detail&aid=3033307&group_id=10894&atid=110894] Here's the patch: ======none diff -ur tcl8.6b3~/generic/tclBinary.c tcl8.6b3/generic/tclBinary.c --- tcl8.6b3~/generic/tclBinary.c 2012-09-17 07:25:44.000000000 -0500 +++ tcl8.6b3/generic/tclBinary.c 2012-10-16 19:04:02.000000000 -0500 @@ -2658,7 +2658,7 @@ Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; - unsigned char *data, *datastart, *dataend, c; + unsigned char *data, *datastart, *dataend, c = '\0'; unsigned char *begin = NULL; unsigned char *cursor = NULL; int strict = 0; @@ -2691,43 +2691,82 @@ while (data < dataend) { unsigned long value = 0; - for (i=0 ; i<4 ; i++) { + /* + * Decode the current block. Each base64 block consists of four input + * characters A-Z, a-z, 0-9, +, or /. Each character supplies six bits + * of output data, so each block's output is 24 bits (three bytes) in + * length. The final block can be shorter by one or two bytes, denoted + * by the input ending with one or two ='s, respectively. + */ + for (i = 0; i < 4; i++) { + /* + * Get the next input character. At end of input, pad with at most + * two ='s. If more than two ='s would be needed, instead discard + * the block read thus far. + */ if (data < dataend) { c = *data++; + } else if (i > 1) { + c = '='; + } else { + cut += 3; + break; + } - if (c >= 'A' && c <= 'Z') { - value = (value << 6) | ((c - 'A') & 0x3f); - } else if (c >= 'a' && c <= 'z') { - value = (value << 6) | ((c - 'a' + 26) & 0x3f); - } else if (c >= '0' && c <= '9') { - value = (value << 6) | ((c - '0' + 52) & 0x3f); - } else if (c == '+') { - value = (value << 6) | 0x3e; - } else if (c == '/') { - value = (value << 6) | 0x3f; - } else if (c == '=') { + /* + * Load the character into the block value. Handle ='s specially + * because they're only valid as the last character or two of the + * final block of input. Unless strict mode is enabled, skip any + * input whitespace characters. + */ + if (cut) { + if (c == '=' && i > 1) { value <<= 6; - if (cut < 2) { - cut++; - } - } else { - if (strict || !isspace(c)) { - goto bad64; - } + cut++; + } else if (!strict && isspace(c)) { i--; - continue; + } else { + goto bad64; } - } else { + } else if (c >= 'A' && c <= 'Z') { + value = (value << 6) | ((c - 'A') & 0x3f); + } else if (c >= 'a' && c <= 'z') { + value = (value << 6) | ((c - 'a' + 26) & 0x3f); + } else if (c >= '0' && c <= '9') { + value = (value << 6) | ((c - '0' + 52) & 0x3f); + } else if (c == '+') { + value = (value << 6) | 0x3e; + } else if (c == '/') { + value = (value << 6) | 0x3f; + } else if (c == '=') { value <<= 6; cut++; + } else if (strict || !isspace(c)) { + goto bad64; + } else { + i--; } } *cursor++ = UCHAR((value >> 16) & 0xff); *cursor++ = UCHAR((value >> 8) & 0xff); *cursor++ = UCHAR(value & 0xff); - } - if (cut > size) { - cut = size; + + /* + * Since = is only valid within the final block, if it was encountered + * but there are still more input characters, confirm that strict mode + * is off and all subsequent characters are whitespace. + */ + if (cut && data < dataend) { + if (strict) { + goto bad64; + } else { + for (; data < dataend; data++) { + if (!isspace(*data)) { + goto bad64; + } + } + } + } } Tcl_SetByteArrayLength(resultObj, cursor - begin - cut); Tcl_SetObjResult(interp, resultObj); diff -ur tcl8.6b3~/tests/binary.test tcl8.6b3/tests/binary.test --- tcl8.6b3~/tests/binary.test 2012-06-26 08:59:02.000000000 -0500 +++ tcl8.6b3/tests/binary.test 2012-10-16 18:43:50.000000000 -0500 @@ -2642,6 +2642,27 @@ test binary-73.24 {binary decode base64} -body { string length [binary decode base64 " "] } -result 0 +test binary-73.25 {binary decode base64} -body { + list [string length [set r [binary decode base64 WA==\n]]] $r +} -result {1 X} +test binary-73.26 {binary decode base64} -body { + list [string length [set r [binary decode base64 WFk=\n]]] $r +} -result {2 XY} +test binary-73.27 {binary decode base64} -body { + list [string length [set r [binary decode base64 WFla\n]]] $r +} -result {3 XYZ} +test binary-73.28 {binary decode base64} -body { + list [string length [set r [binary decode base64 -strict WA==\n]]] $r +} -returnCodes error -match glob -result {invalid base64 character *} +test binary-73.29 {binary decode base64} -body { + list [string length [set r [binary decode base64 -strict WFk=\n]]] $r +} -returnCodes error -match glob -result {invalid base64 character *} +test binary-73.30 {binary decode base64} -body { + list [string length [set r [binary decode base64 -strict WFla\n]]] $r +} -returnCodes error -match glob -result {invalid base64 character *} +test binary-73.31 {binary decode base64} -body { + list [string length [set r [binary decode base64 WA==WFla]]] $r +} -returnCodes error -match glob -result {invalid base64 character *} test binary-74.1 {binary encode uuencode} -body { binary encode uuencode ====== Hopefully the Wiki won't destroy all the tabs... *sigh* Yup, it ate my tabs. Oh well, you can still read it. Here's the intended file, formatted in base64 of course. :^) ======none begin-base64 644 tcl8.6b3-base64decode.patch ZGlmZiAtdXIgdGNsOC42YjN+L2dlbmVyaWMvdGNsQmluYXJ5LmMgdGNsOC42 YjMvZ2VuZXJpYy90Y2xCaW5hcnkuYwotLS0gdGNsOC42YjN+L2dlbmVyaWMv dGNsQmluYXJ5LmMJMjAxMi0wOS0xNyAwNzoyNTo0NC4wMDAwMDAwMDAgLTA1 MDAKKysrIHRjbDguNmIzL2dlbmVyaWMvdGNsQmluYXJ5LmMJMjAxMi0xMC0x NiAxOTowNDowMi4wMDAwMDAwMDAgLTA1MDAKQEAgLTI2NTgsNyArMjY1OCw3 IEBACiAgICAgVGNsX09iaiAqY29uc3Qgb2JqdltdKQogewogICAgIFRjbF9P YmogKnJlc3VsdE9iaiA9IE5VTEw7Ci0gICAgdW5zaWduZWQgY2hhciAqZGF0 YSwgKmRhdGFzdGFydCwgKmRhdGFlbmQsIGM7CisgICAgdW5zaWduZWQgY2hh ciAqZGF0YSwgKmRhdGFzdGFydCwgKmRhdGFlbmQsIGMgPSAnXDAnOwogICAg IHVuc2lnbmVkIGNoYXIgKmJlZ2luID0gTlVMTDsKICAgICB1bnNpZ25lZCBj aGFyICpjdXJzb3IgPSBOVUxMOwogICAgIGludCBzdHJpY3QgPSAwOwpAQCAt MjY5MSw0MyArMjY5MSw4MiBAQAogICAgIHdoaWxlIChkYXRhIDwgZGF0YWVu ZCkgewogCXVuc2lnbmVkIGxvbmcgdmFsdWUgPSAwOwogCi0JZm9yIChpPTAg OyBpPDQgOyBpKyspIHsKKwkvKgorCSAqIERlY29kZSB0aGUgY3VycmVudCBi bG9jay4gRWFjaCBiYXNlNjQgYmxvY2sgY29uc2lzdHMgb2YgZm91ciBpbnB1 dAorCSAqIGNoYXJhY3RlcnMgQS1aLCBhLXosIDAtOSwgKywgb3IgLy4gRWFj aCBjaGFyYWN0ZXIgc3VwcGxpZXMgc2l4IGJpdHMKKwkgKiBvZiBvdXRwdXQg ZGF0YSwgc28gZWFjaCBibG9jaydzIG91dHB1dCBpcyAyNCBiaXRzICh0aHJl ZSBieXRlcykgaW4KKwkgKiBsZW5ndGguIFRoZSBmaW5hbCBibG9jayBjYW4g YmUgc2hvcnRlciBieSBvbmUgb3IgdHdvIGJ5dGVzLCBkZW5vdGVkCisJICog YnkgdGhlIGlucHV0IGVuZGluZyB3aXRoIG9uZSBvciB0d28gPSdzLCByZXNw ZWN0aXZlbHkuCisJICovCisJZm9yIChpID0gMDsgaSA8IDQ7IGkrKykgewor CSAgICAvKgorCSAgICAgKiBHZXQgdGhlIG5leHQgaW5wdXQgY2hhcmFjdGVy LiBBdCBlbmQgb2YgaW5wdXQsIHBhZCB3aXRoIGF0IG1vc3QKKwkgICAgICog dHdvID0ncy4gSWYgbW9yZSB0aGFuIHR3byA9J3Mgd291bGQgYmUgbmVlZGVk LCBpbnN0ZWFkIGRpc2NhcmQKKwkgICAgICogdGhlIGJsb2NrIHJlYWQgdGh1 cyBmYXIuCisJICAgICAqLwogCSAgICBpZiAoZGF0YSA8IGRhdGFlbmQpIHsK IAkJYyA9ICpkYXRhKys7CisJICAgIH0gZWxzZSBpZiAoaSA+IDEpIHsKKwkJ YyA9ICc9JzsKKwkgICAgfSBlbHNlIHsKKwkJY3V0ICs9IDM7CisJCWJyZWFr OworCSAgICB9CiAKLQkJaWYgKGMgPj0gJ0EnICYmIGMgPD0gJ1onKSB7Ci0J CSAgICB2YWx1ZSA9ICh2YWx1ZSA8PCA2KSB8ICgoYyAtICdBJykgJiAweDNm KTsKLQkJfSBlbHNlIGlmIChjID49ICdhJyAmJiBjIDw9ICd6JykgewotCQkg ICAgdmFsdWUgPSAodmFsdWUgPDwgNikgfCAoKGMgLSAnYScgKyAyNikgJiAw eDNmKTsKLQkJfSBlbHNlIGlmIChjID49ICcwJyAmJiBjIDw9ICc5Jykgewot CQkgICAgdmFsdWUgPSAodmFsdWUgPDwgNikgfCAoKGMgLSAnMCcgKyA1Mikg JiAweDNmKTsKLQkJfSBlbHNlIGlmIChjID09ICcrJykgewotCQkgICAgdmFs dWUgPSAodmFsdWUgPDwgNikgfCAweDNlOwotCQl9IGVsc2UgaWYgKGMgPT0g Jy8nKSB7Ci0JCSAgICB2YWx1ZSA9ICh2YWx1ZSA8PCA2KSB8IDB4M2Y7Ci0J CX0gZWxzZSBpZiAoYyA9PSAnPScpIHsKKwkgICAgLyoKKwkgICAgICogTG9h ZCB0aGUgY2hhcmFjdGVyIGludG8gdGhlIGJsb2NrIHZhbHVlLiBIYW5kbGUg PSdzIHNwZWNpYWxseQorCSAgICAgKiBiZWNhdXNlIHRoZXkncmUgb25seSB2 YWxpZCBhcyB0aGUgbGFzdCBjaGFyYWN0ZXIgb3IgdHdvIG9mIHRoZQorCSAg ICAgKiBmaW5hbCBibG9jayBvZiBpbnB1dC4gVW5sZXNzIHN0cmljdCBtb2Rl IGlzIGVuYWJsZWQsIHNraXAgYW55CisJICAgICAqIGlucHV0IHdoaXRlc3Bh Y2UgY2hhcmFjdGVycy4KKwkgICAgICovCisJICAgIGlmIChjdXQpIHsKKwkJ aWYgKGMgPT0gJz0nICYmIGkgPiAxKSB7CiAJCSAgICB2YWx1ZSA8PD0gNjsK LQkJICAgIGlmIChjdXQgPCAyKSB7Ci0JCQljdXQrKzsKLQkJICAgIH0KLQkJ fSBlbHNlIHsKLQkJICAgIGlmIChzdHJpY3QgfHwgIWlzc3BhY2UoYykpIHsK LQkJCWdvdG8gYmFkNjQ7Ci0JCSAgICB9CisJCSAgICBjdXQrKzsKKwkJfSBl bHNlIGlmICghc3RyaWN0ICYmIGlzc3BhY2UoYykpIHsKIAkJICAgIGktLTsK LQkJICAgIGNvbnRpbnVlOworCQl9IGVsc2UgeworCQkgICAgZ290byBiYWQ2 NDsKIAkJfQotCSAgICB9IGVsc2UgeworCSAgICB9IGVsc2UgaWYgKGMgPj0g J0EnICYmIGMgPD0gJ1onKSB7CisJCXZhbHVlID0gKHZhbHVlIDw8IDYpIHwg KChjIC0gJ0EnKSAmIDB4M2YpOworCSAgICB9IGVsc2UgaWYgKGMgPj0gJ2En ICYmIGMgPD0gJ3onKSB7CisJCXZhbHVlID0gKHZhbHVlIDw8IDYpIHwgKChj IC0gJ2EnICsgMjYpICYgMHgzZik7CisJICAgIH0gZWxzZSBpZiAoYyA+PSAn MCcgJiYgYyA8PSAnOScpIHsKKwkJdmFsdWUgPSAodmFsdWUgPDwgNikgfCAo KGMgLSAnMCcgKyA1MikgJiAweDNmKTsKKwkgICAgfSBlbHNlIGlmIChjID09 ICcrJykgeworCQl2YWx1ZSA9ICh2YWx1ZSA8PCA2KSB8IDB4M2U7CisJICAg IH0gZWxzZSBpZiAoYyA9PSAnLycpIHsKKwkJdmFsdWUgPSAodmFsdWUgPDwg NikgfCAweDNmOworCSAgICB9IGVsc2UgaWYgKGMgPT0gJz0nKSB7CiAJCXZh bHVlIDw8PSA2OwogCQljdXQrKzsKKwkgICAgfSBlbHNlIGlmIChzdHJpY3Qg fHwgIWlzc3BhY2UoYykpIHsKKwkJZ290byBiYWQ2NDsKKwkgICAgfSBlbHNl IHsKKwkJaS0tOwogCSAgICB9CiAJfQogCSpjdXJzb3IrKyA9IFVDSEFSKCh2 YWx1ZSA+PiAxNikgJiAweGZmKTsKIAkqY3Vyc29yKysgPSBVQ0hBUigodmFs dWUgPj4gOCkgJiAweGZmKTsKIAkqY3Vyc29yKysgPSBVQ0hBUih2YWx1ZSAm IDB4ZmYpOwotICAgIH0KLSAgICBpZiAoY3V0ID4gc2l6ZSkgewotCWN1dCA9 IHNpemU7CisKKwkvKgorCSAqIFNpbmNlID0gaXMgb25seSB2YWxpZCB3aXRo aW4gdGhlIGZpbmFsIGJsb2NrLCBpZiBpdCB3YXMgZW5jb3VudGVyZWQKKwkg KiBidXQgdGhlcmUgYXJlIHN0aWxsIG1vcmUgaW5wdXQgY2hhcmFjdGVycywg Y29uZmlybSB0aGF0IHN0cmljdCBtb2RlCisJICogaXMgb2ZmIGFuZCBhbGwg c3Vic2VxdWVudCBjaGFyYWN0ZXJzIGFyZSB3aGl0ZXNwYWNlLgorCSAqLwor CWlmIChjdXQgJiYgZGF0YSA8IGRhdGFlbmQpIHsKKwkgICAgaWYgKHN0cmlj dCkgeworCQlnb3RvIGJhZDY0OworCSAgICB9IGVsc2UgeworCQlmb3IgKDsg ZGF0YSA8IGRhdGFlbmQ7IGRhdGErKykgeworCQkgICAgaWYgKCFpc3NwYWNl KCpkYXRhKSkgeworCQkJZ290byBiYWQ2NDsKKwkJICAgIH0KKwkJfQorCSAg ICB9CisJfQogICAgIH0KICAgICBUY2xfU2V0Qnl0ZUFycmF5TGVuZ3RoKHJl c3VsdE9iaiwgY3Vyc29yIC0gYmVnaW4gLSBjdXQpOwogICAgIFRjbF9TZXRP YmpSZXN1bHQoaW50ZXJwLCByZXN1bHRPYmopOwpkaWZmIC11ciB0Y2w4LjZi M34vdGVzdHMvYmluYXJ5LnRlc3QgdGNsOC42YjMvdGVzdHMvYmluYXJ5LnRl c3QKLS0tIHRjbDguNmIzfi90ZXN0cy9iaW5hcnkudGVzdAkyMDEyLTA2LTI2 IDA4OjU5OjAyLjAwMDAwMDAwMCAtMDUwMAorKysgdGNsOC42YjMvdGVzdHMv YmluYXJ5LnRlc3QJMjAxMi0xMC0xNiAxODo0Mzo1MC4wMDAwMDAwMDAgLTA1 MDAKQEAgLTI2NDIsNiArMjY0MiwyNyBAQAogdGVzdCBiaW5hcnktNzMuMjQg e2JpbmFyeSBkZWNvZGUgYmFzZTY0fSAtYm9keSB7CiAgICAgc3RyaW5nIGxl bmd0aCBbYmluYXJ5IGRlY29kZSBiYXNlNjQgIiAiXQogfSAtcmVzdWx0IDAK K3Rlc3QgYmluYXJ5LTczLjI1IHtiaW5hcnkgZGVjb2RlIGJhc2U2NH0gLWJv ZHkgeworICAgIGxpc3QgW3N0cmluZyBsZW5ndGggW3NldCByIFtiaW5hcnkg ZGVjb2RlIGJhc2U2NCBXQT09XG5dXV0gJHIKK30gLXJlc3VsdCB7MSBYfQor dGVzdCBiaW5hcnktNzMuMjYge2JpbmFyeSBkZWNvZGUgYmFzZTY0fSAtYm9k eSB7CisgICAgbGlzdCBbc3RyaW5nIGxlbmd0aCBbc2V0IHIgW2JpbmFyeSBk ZWNvZGUgYmFzZTY0IFdGaz1cbl1dXSAkcgorfSAtcmVzdWx0IHsyIFhZfQor dGVzdCBiaW5hcnktNzMuMjcge2JpbmFyeSBkZWNvZGUgYmFzZTY0fSAtYm9k eSB7CisgICAgbGlzdCBbc3RyaW5nIGxlbmd0aCBbc2V0IHIgW2JpbmFyeSBk ZWNvZGUgYmFzZTY0IFdGbGFcbl1dXSAkcgorfSAtcmVzdWx0IHszIFhZWn0K K3Rlc3QgYmluYXJ5LTczLjI4IHtiaW5hcnkgZGVjb2RlIGJhc2U2NH0gLWJv ZHkgeworICAgIGxpc3QgW3N0cmluZyBsZW5ndGggW3NldCByIFtiaW5hcnkg ZGVjb2RlIGJhc2U2NCAtc3RyaWN0IFdBPT1cbl1dXSAkcgorfSAtcmV0dXJu Q29kZXMgZXJyb3IgLW1hdGNoIGdsb2IgLXJlc3VsdCB7aW52YWxpZCBiYXNl NjQgY2hhcmFjdGVyICp9Cit0ZXN0IGJpbmFyeS03My4yOSB7YmluYXJ5IGRl Y29kZSBiYXNlNjR9IC1ib2R5IHsKKyAgICBsaXN0IFtzdHJpbmcgbGVuZ3Ro IFtzZXQgciBbYmluYXJ5IGRlY29kZSBiYXNlNjQgLXN0cmljdCBXRms9XG5d XV0gJHIKK30gLXJldHVybkNvZGVzIGVycm9yIC1tYXRjaCBnbG9iIC1yZXN1 bHQge2ludmFsaWQgYmFzZTY0IGNoYXJhY3RlciAqfQordGVzdCBiaW5hcnkt NzMuMzAge2JpbmFyeSBkZWNvZGUgYmFzZTY0fSAtYm9keSB7CisgICAgbGlz dCBbc3RyaW5nIGxlbmd0aCBbc2V0IHIgW2JpbmFyeSBkZWNvZGUgYmFzZTY0 IC1zdHJpY3QgV0ZsYVxuXV1dICRyCit9IC1yZXR1cm5Db2RlcyBlcnJvciAt bWF0Y2ggZ2xvYiAtcmVzdWx0IHtpbnZhbGlkIGJhc2U2NCBjaGFyYWN0ZXIg Kn0KK3Rlc3QgYmluYXJ5LTczLjMxIHtiaW5hcnkgZGVjb2RlIGJhc2U2NH0g LWJvZHkgeworICAgIGxpc3QgW3N0cmluZyBsZW5ndGggW3NldCByIFtiaW5h cnkgZGVjb2RlIGJhc2U2NCBXQT09V0ZsYV1dXSAkcgorfSAtcmV0dXJuQ29k ZXMgZXJyb3IgLW1hdGNoIGdsb2IgLXJlc3VsdCB7aW52YWxpZCBiYXNlNjQg Y2hhcmFjdGVyICp9CiAKIHRlc3QgYmluYXJ5LTc0LjEge2JpbmFyeSBlbmNv ZGUgdXVlbmNvZGV9IC1ib2R5IHsKICAgICBiaW5hcnkgZW5jb2RlIHV1ZW5j b2RlCg== ==== ======