LCOV - code coverage report
Current view: top level - lib/util/charset/tests - convert_string.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 713 739 96.5 %
Date: 2021-08-25 13:27:56 Functions: 24 24 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for the charcnv functions
       4             : 
       5             :    Copyright (C) Andrew Bartlett 2011
       6             :    
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "torture/torture.h"
      23             : #include "lib/util/charset/charset.h"
      24             : #include "param/param.h"
      25             : #include "lib/util/base64.h"
      26             : 
      27             : struct torture_suite *torture_local_convert_string_handle(TALLOC_CTX *mem_ctx);
      28             : struct torture_suite *torture_local_string_case_handle(TALLOC_CTX *mem_ctx);
      29             : struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx);
      30             : struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx);
      31             : 
      32             : /* The text below is in ancient and a latin charset transliteration of
      33             :  * greek, and an english translation.  It from Apology by Plato and sourced from
      34             :  * http://en.wikipedia.org/w/index.php?title=Ancient_Greek&oldid=421361065#Example_text
      35             :  */
      36             : 
      37             : const char *plato_english_ascii = 
      38             :         "What you, men of Athens, have learned from my accusers, I do not"
      39             :         " know: but I, for my part, nearly forgot who I was thanks to them since"
      40             :         " they spoke so persuasively. And yet, of the truth, they have spoken,"
      41             :         " one might say, nothing at all.";
      42             : 
      43             : const char *plato_english_utf16le_base64 =
      44             :         "VwBoAGEAdAAgAHkAbwB1ACwAIABtAGUAbgAgAG8AZgAgAEEAdABoAGUAbgBzACwAIABoAGEAdgBl"
      45             :         "ACAAbABlAGEAcgBuAGUAZAAgAGYAcgBvAG0AIABtAHkAIABhAGMAYwB1AHMAZQByAHMALAAgAEkA"
      46             :         "IABkAG8AIABuAG8AdAAgAGsAbgBvAHcAOgAgAGIAdQB0ACAASQAsACAAZgBvAHIAIABtAHkAIABw"
      47             :         "AGEAcgB0ACwAIABuAGUAYQByAGwAeQAgAGYAbwByAGcAbwB0ACAAdwBoAG8AIABJACAAdwBhAHMA"
      48             :         "IAB0AGgAYQBuAGsAcwAgAHQAbwAgAHQAaABlAG0AIABzAGkAbgBjAGUAIAB0AGgAZQB5ACAAcwBw"
      49             :         "AG8AawBlACAAcwBvACAAcABlAHIAcwB1AGEAcwBpAHYAZQBsAHkALgAgAEEAbgBkACAAeQBlAHQA"
      50             :         "LAAgAG8AZgAgAHQAaABlACAAdAByAHUAdABoACwAIAB0AGgAZQB5ACAAaABhAHYAZQAgAHMAcABv"
      51             :         "AGsAZQBuACwAIABvAG4AZQAgAG0AaQBnAGgAdAAgAHMAYQB5ACwAIABuAG8AdABoAGkAbgBnACAA"
      52             :         "YQB0ACAAYQBsAGwALgA=";
      53             : 
      54             : static const char *plato_utf8_base64 = 
      55             :         "4b2Nz4TOuSDOvOG9ss69IOG9kc68zrXhv5bPgiwg4b2mIOG8hM69zrTPgc61z4IgzobOuM63zr3O"
      56             :         "seG/ls6/zrksIM+AzrXPgM+Mzr3OuM6xz4TOtSDhvZHPgOG9uCDPhOG/ts69IOG8kM684b+2zr0g"
      57             :         "zrrOsc+EzrfOs8+Mz4HPic69LCDOv+G9kM66IM6/4by2zrTOsTog4byQzrPhvbwgzrQnIM6/4b2W"
      58             :         "zr0gzrrOseG9tiDOseG9kM+E4b24z4Ig4b2Rz4AnIM6x4b2Qz4Thv7bOvSDhvYDOu86vzrPOv8+F"
      59             :         "IOG8kM68zrHPhc+Ezr/hv6Yg4byQz4DOtc67zrHOuM+MzrzOt869LCDOv+G9lc+Ez4kgz4DOuc64"
      60             :         "zrHOveG/ts+CIOG8lM67zrXOs86/zr0uIM6azrHOr8+Ezr/OuSDhvIDOu863zrjOrc+CIM6zzrUg"
      61             :         "4b2hz4Ig4byUz4DOv8+CIM614bywz4DOteG/ls69IM6/4b2QzrThvbLOvSDOteG8sM+Bzq7Ous6x"
      62             :         "z4POuc69Lg==";
      63             : 
      64             : static const char *plato_utf16le_base64 = 
      65             :         "TR/EA7kDIAC8A3IfvQMgAFEfvAO1A9YfwgMsACAAZh8gAAQfvQO0A8EDtQPCAyAAhgO4A7cDvQOx"
      66             :         "A9YfvwO5AywAIADAA7UDwAPMA70DuAOxA8QDtQMgAFEfwAN4HyAAxAP2H70DIAAQH7wD9h+9AyAA"
      67             :         "ugOxA8QDtwOzA8wDwQPJA70DLAAgAL8DUB+6AyAAvwM2H7QDsQM6ACAAEB+zA3wfIAC0AycAIAC/"
      68             :         "A1YfvQMgALoDsQN2HyAAsQNQH8QDeB/CAyAAUR/AAycAIACxA1AfxAP2H70DIABAH7sDrwOzA78D"
      69             :         "xQMgABAfvAOxA8UDxAO/A+YfIAAQH8ADtQO7A7EDuAPMA7wDtwO9AywAIAC/A1UfxAPJAyAAwAO5"
      70             :         "A7gDsQO9A/YfwgMgABQfuwO1A7MDvwO9Ay4AIACaA7EDrwPEA78DuQMgAAAfuwO3A7gDrQPCAyAA"
      71             :         "swO1AyAAYR/CAyAAFB/AA78DwgMgALUDMB/AA7UD1h+9AyAAvwNQH7QDch+9AyAAtQMwH8EDrgO6"
      72             :         "A7EDwwO5A70DLgA=";
      73             : 
      74             : static const char *plato_latin_utf8_base64 = 
      75             :         "SMOzdGkgbcOobiBodW1lw65zLCDDtCDDoW5kcmVzIEF0aMSTbmHDrm9pLCBwZXDDs250aGF0ZSBo"
      76             :         "dXDDsiB0w7RuIGVtw7RuIGthdMSTZ8OzcsWNbiwgb3VrIG/DrmRhOiBlZ+G5kSBkJyBvw7tuIGth"
      77             :         "w6wgYXV0w7JzIGh1cCcgYXV0xY1uIG9sw61nb3UgZW1hdXRvw7sgZXBlbGF0aMOzbcSTbiwgaG/D"
      78             :         "unTFjSBwaXRoYW7DtHMgw6lsZWdvbi4gS2HDrXRvaSBhbMSTdGjDqXMgZ2UgaMWNcyDDqXBvcyBl"
      79             :         "aXBlw65uIG91ZMOobiBlaXLhuJdrYXNpbi4=";
      80             : 
      81             : static const char *plato_latin_utf16le_base64 = 
      82             :         "SADzAHQAaQAgAG0A6ABuACAAaAB1AG0AZQDuAHMALAAgAPQAIADhAG4AZAByAGUAcwAgAEEAdABo"
      83             :         "ABMBbgBhAO4AbwBpACwAIABwAGUAcADzAG4AdABoAGEAdABlACAAaAB1AHAA8gAgAHQA9ABuACAA"
      84             :         "ZQBtAPQAbgAgAGsAYQB0ABMBZwDzAHIATQFuACwAIABvAHUAawAgAG8A7gBkAGEAOgAgAGUAZwBR"
      85             :         "HiAAZAAnACAAbwD7AG4AIABrAGEA7AAgAGEAdQB0APIAcwAgAGgAdQBwACcAIABhAHUAdABNAW4A"
      86             :         "IABvAGwA7QBnAG8AdQAgAGUAbQBhAHUAdABvAPsAIABlAHAAZQBsAGEAdABoAPMAbQATAW4ALAAg"
      87             :         "AGgAbwD6AHQATQEgAHAAaQB0AGgAYQBuAPQAcwAgAOkAbABlAGcAbwBuAC4AIABLAGEA7QB0AG8A"
      88             :         "aQAgAGEAbAATAXQAaADpAHMAIABnAGUAIABoAE0BcwAgAOkAcABvAHMAIABlAGkAcABlAO4AbgAg"
      89             :         "AG8AdQBkAOgAbgAgAGUAaQByABceawBhAHMAaQBuAC4A";
      90             : 
      91             : static const char *gd_utf8_base64 = "R8O8bnRoZXIgRGVzY2huZXI=";
      92             : static const char *gd_utf8_upper_base64 = "R8OcTlRIRVIgREVTQ0hORVI=";
      93             : static const char *gd_utf8_lower_base64 = "Z8O8bnRoZXIgZGVzY2huZXI=";
      94             : static const char *gd_cp850_base64 = "R4FudGhlciBEZXNjaG5lcg==";
      95             : static const char *gd_cp850_upper_base64 = "R5pOVEhFUiBERVNDSE5FUg==";
      96             : static const char *gd_cp850_lower_base64 = "Z4FudGhlciBkZXNjaG5lcg==";
      97             : static const char *gd_iso8859_1_base64 = "R/xudGhlciBEZXNjaG5lcg==";
      98             : static const char *gd_utf16le_base64 = "RwD8AG4AdABoAGUAcgAgAEQAZQBzAGMAaABuAGUAcgA=";
      99             : /* täst */
     100             : static const char *utf8_nfc_base64 = "dMOkc3QA";
     101             : /* täst, where ä = a + combining diaeresis */
     102             : static const char *utf8_nfd_base64 = "dGHMiHN0AA==";
     103             : 
     104             : /*
     105             :  * These cp850 bytes correspond to high Unicode codes, stretching out to
     106             :  * 3-byte sequences in utf-8.
     107             :  */
     108             : static const char *cp850_high_points = "\xb9\xba\xbb\xbc\xcd\xce";
     109             : static const char *utf8_high_points = "╣║╗╝═╬";
     110             : 
     111           2 : static bool test_cp850_high_points(struct torture_context *tctx)
     112             : {
     113           2 :         struct smb_iconv_handle *iconv_handle = NULL;
     114           2 :         DATA_BLOB cp850 = data_blob_string_const(cp850_high_points);
     115             :         DATA_BLOB utf8;
     116             :         DATA_BLOB cp850_return;
     117             : 
     118           2 :         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8",
     119           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx,
     120             :                                                                 NULL,
     121             :                                                                 "iconv",
     122             :                                                                 "use_builtin_handlers",
     123             :                                                                 true));
     124             : 
     125           2 :         torture_assert(tctx, iconv_handle, "creating iconv handle");
     126             : 
     127           2 :         torture_assert(tctx,
     128             :                        convert_string_talloc_handle(tctx, iconv_handle,
     129             :                                                     CH_DOS, CH_UTF8,
     130             :                                                     cp850.data, cp850.length,
     131             :                                                     (void *)&utf8.data, &utf8.length),
     132             :                        "conversion from CP850 to UTF-8");
     133             : 
     134           2 :         torture_assert(tctx, utf8.length == cp850.length * 3,
     135             :                        "CP850 high bytes expand to the right size");
     136             : 
     137           2 :         torture_assert(tctx,
     138             :                        memcmp(utf8.data, utf8_high_points, utf8.length) == 0,
     139             :                        "cp850 converted to utf8 matches expected value");
     140             : 
     141           2 :         torture_assert(tctx,
     142             :                        convert_string_talloc_handle(tctx, iconv_handle,
     143             :                                                     CH_UTF8, CH_DOS,
     144             :                                                     utf8.data, utf8.length,
     145             :                                                     (void *)&cp850_return.data,
     146             :                                                     &cp850_return.length),
     147             :                        "conversion from UTF-8 back to CP850");
     148             : 
     149           2 :         torture_assert(tctx, data_blob_cmp(&cp850_return, &cp850) == 0,
     150             :                        "UTF-8 returned to CP850 matches the original");
     151           0 :         return true;
     152             : }
     153             : 
     154             : 
     155           2 : static bool test_gd_iso8859_cp850_handle(struct torture_context *tctx)
     156             : {
     157             :         struct smb_iconv_handle *iconv_handle;
     158           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
     159           2 :         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
     160           2 :         DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64);
     161           2 :         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
     162             :         DATA_BLOB gd_output;
     163             :         DATA_BLOB gd_output2;
     164             :         
     165           2 :         talloc_steal(tctx, gd_utf8.data);
     166           2 :         talloc_steal(tctx, gd_cp850.data);
     167           2 :         talloc_steal(tctx, gd_iso8859_1.data);
     168           2 :         talloc_steal(tctx, gd_utf16le.data);
     169             : 
     170           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850",
     171           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     172           2 :         torture_assert(tctx, iconv_handle, "getting iconv handle");
     173             :                 
     174           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     175             :                                                     CH_UTF8, CH_DOS, 
     176             :                                                     gd_utf8.data, gd_utf8.length, 
     177             :                                                     (void *)&gd_output.data, &gd_output.length), 
     178             :                        "conversion from UTF8 to (dos charset) ISO-8859-1");
     179           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect");
     180             :         
     181           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     182             :                                                          CH_UTF8, CH_DOS,
     183             :                                                          gd_utf8.data, gd_utf8.length,
     184             :                                                          (void *)gd_output.data, gd_output.length,
     185             :                                                          &gd_output.length),
     186             :                        "conversion from UTF8 to (dos charset) ISO-8859-1");
     187           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect");
     188             : 
     189             :         /* Short output handling confirmation */
     190           2 :         gd_output.length = 1;
     191           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     192             :                                                          CH_UTF8, CH_DOS,
     193             :                                                          gd_utf8.data, gd_utf8.length,
     194             :                                                          (void *)gd_output.data, gd_output.length,
     195             :                                                          &gd_output.length) == false,
     196             :                        "conversion from UTF8 to (dos charset) ISO-8859-1 should fail due to too short");
     197           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail E2BIG");
     198           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     199           2 :         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect");
     200             : 
     201             :         /* Short output handling confirmation */
     202           2 :         gd_output.length = 2;
     203           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     204             :                                                          CH_UTF8, CH_DOS,
     205             :                                                          gd_utf8.data, gd_utf8.length,
     206             :                                                          (void *)gd_output.data, gd_output.length,
     207             :                                                          &gd_output.length) == false,
     208             :                        "conversion from UTF8 to (dos charset) ISO-8859-1 should fail due to too short");
     209           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail E2BIG");
     210           2 :         torture_assert_int_equal(tctx, gd_output.length, 2, "Should only get 2 char of output");
     211             : 
     212             :         /* Short input handling confirmation */
     213           2 :         gd_output.length = gd_iso8859_1.length;
     214           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     215             :                                                          CH_UTF8, CH_DOS,
     216             :                                                          gd_utf8.data, 2,
     217             :                                                          (void *)gd_output.data, gd_output.length,
     218             :                                                          &gd_output.length) == false,
     219             :                        "conversion from UTF8 to (dos charset) ISO-8859-1 should fail due to too short");
     220           2 :         torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to (dos charset) ISO-8859-1 should fail EINVAL");
     221           1 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     222             : 
     223             :         /* Short output handling confirmation */
     224           1 :         gd_output.length = 1;
     225           1 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     226             :                                                          CH_UTF16LE, CH_UTF8,
     227             :                                                          gd_utf16le.data, gd_utf16le.length,
     228             :                                                          (void *)gd_output.data, gd_output.length,
     229             :                                                          &gd_output.length) == false,
     230             :                        "conversion from UTF16 to UTF8 should fail due to too short");
     231           1 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to (utf8 charset) ISO-8859-1 should fail E2BIG");
     232           1 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     233           1 :         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF16 to UTF8 incorrect");
     234             : 
     235             :         /* Short output handling confirmation */
     236           1 :         gd_output.length = 3;
     237           1 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     238             :                                                          CH_UTF16LE, CH_UTF8,
     239             :                                                          gd_utf16le.data, gd_utf16le.length,
     240             :                                                          (void *)gd_output.data, gd_output.length,
     241             :                                                          &gd_output.length) == false,
     242             :                        "conversion from UTF16 to UTF8 should fail due to too short");
     243           1 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to (utf8 charset) ISO-8859-1 should fail E2BIG");
     244           1 :         torture_assert_int_equal(tctx, gd_output.length, 3, "Should get 3 bytes output for UTF8");
     245             : 
     246             :         /* Short input handling confirmation */
     247           1 :         gd_output.length = gd_utf8.length;
     248           1 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     249             :                                                          CH_UTF16LE, CH_UTF8,
     250             :                                                          gd_utf16le.data, 3,
     251             :                                                          (void *)gd_output.data, gd_output.length,
     252             :                                                          &gd_output.length) == false,
     253             :                        "conversion from UTF16 to UTF8 should fail due to too short");
     254           1 :         torture_assert_errno_equal(tctx, EINVAL, "conversion from short UTF16 to UTF8 should fail EINVAL");
     255           1 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     256             : 
     257           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     258             :                                                     CH_UTF8, CH_UNIX, 
     259             :                                                     gd_utf8.data, gd_utf8.length, 
     260             :                                                     (void *)&gd_output.data, &gd_output.length), 
     261             :                        "conversion from UTF8 to (unix charset) CP850");
     262           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF8 to (unix charset) CP850 incorrect");
     263             :         
     264           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     265             :                                                     CH_UTF8, CH_UTF8, 
     266             :                                                     gd_utf8.data, gd_utf8.length, 
     267             :                                                     (void *)&gd_output.data, &gd_output.length), 
     268             :                        "conversion from UTF8 to UTF8");
     269           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF8 to UTF8 incorrect");
     270             :         
     271           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     272             :                                                     CH_UTF16LE, CH_DOS, 
     273             :                                                     gd_utf16le.data, gd_utf16le.length, 
     274             :                                                     (void *)&gd_output.data, &gd_output.length),
     275             :                        "conversion from UTF16LE to (dos charset) ISO-8859-1");
     276           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect");
     277             :         
     278           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     279             :                                                     CH_DOS, CH_UTF16LE, 
     280             :                                                     gd_output.data, gd_output.length, 
     281             :                                                     (void *)&gd_output2.data, &gd_output2.length),
     282             :                        "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE");
     283           1 :         torture_assert_data_blob_equal(tctx, gd_output2, gd_utf16le,  "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE");
     284             :         
     285           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     286             :                                                     CH_UTF16LE, CH_UNIX, 
     287             :                                                     gd_utf16le.data, gd_utf16le.length, 
     288             :                                                     (void *)&gd_output.data, &gd_output.length),
     289             :                        "conversion from UTF16LE to (unix charset) CP850");
     290           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
     291             :         
     292           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     293             :                                                     CH_UTF16LE, CH_UTF8, 
     294             :                                                     gd_utf16le.data, gd_utf16le.length, 
     295             :                                                     (void *)&gd_output.data, &gd_output.length), 
     296             :                        "conversion from UTF16LE to UTF8");
     297           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 incorrect");
     298             :         
     299           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     300             :                                                     CH_DOS, CH_DOS, 
     301             :                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
     302             :                                                     (void *)&gd_output.data, &gd_output.length),
     303             :                        "conversion from (dos charset) ISO-8859-1 to (dos charset) ISO-8859-1");
     304           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect");
     305             :         
     306           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     307             :                                                     CH_DOS, CH_UNIX, 
     308             :                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
     309             :                                                     (void *)&gd_output.data, &gd_output.length), 
     310             :                        "conversion from (dos charset) ISO-8859-1 to (unix charset) CP850");
     311           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
     312             :         
     313           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     314             :                                                     CH_DOS, CH_UTF8, 
     315             :                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
     316             :                                                     (void *)&gd_output.data, &gd_output.length), 
     317             :                        "conversion from (dos charset) ISO-8859-1 to UTF8");
     318           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 incorrect");
     319             : 
     320           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     321             :                                                     CH_DOS, CH_UTF16LE, 
     322             :                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
     323             :                                                     (void *)&gd_output.data, &gd_output.length), 
     324             :                        "conversion from (dos charset) ISO-8859-1 to UTF16LE");
     325           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion from (dos charset) ISO-8859-1 to UTF16LE");
     326           1 :         torture_assert_int_equal(tctx,
     327             :                                  strlen_m_ext_handle(iconv_handle,
     328             :                                                      (const char *)gd_iso8859_1.data,
     329             :                                                      CH_DOS, CH_UTF16LE),
     330             :                                  gd_output.length / 2,
     331             :                                  "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again");
     332             : 
     333           1 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
     334             :                                                     CH_DOS, CH_UTF8,
     335             :                                                     gd_iso8859_1.data, gd_iso8859_1.length,
     336             :                                                     (void *)&gd_output.data, &gd_output.length),
     337             :                        "conversion from (dos charset) ISO-8859-1 to UTF8");
     338           1 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from (dos charset) ISO-8859-1 to UTF8");
     339           1 :         torture_assert_int_equal(tctx,
     340             :                                  strlen_m_ext_handle(iconv_handle,
     341             :                                                      (const char *)gd_iso8859_1.data,
     342             :                                                      CH_DOS, CH_UTF8),
     343             :                                  gd_output.length,
     344             :                                  "checking strlen_m_ext of conversion from (dos charset) ISO-8859-1 to UTF8");
     345           0 :         return true;
     346             : }
     347             : 
     348           2 : static bool test_gd_minus_1_handle(struct torture_context *tctx)
     349             : {
     350             :         struct smb_iconv_handle *iconv_handle;
     351           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
     352           2 :         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
     353           2 :         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
     354             :         DATA_BLOB gd_output;
     355             :         DATA_BLOB gd_utf8_terminated;
     356             :         DATA_BLOB gd_cp850_terminated;
     357             :         DATA_BLOB gd_utf16le_terminated;
     358             :         
     359           2 :         talloc_steal(tctx, gd_utf8.data);
     360           2 :         talloc_steal(tctx, gd_cp850.data);
     361           2 :         talloc_steal(tctx, gd_utf16le.data);
     362             : 
     363           2 :         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "CP850", 
     364           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     365           2 :         torture_assert(tctx, iconv_handle, "getting iconv handle");
     366             : 
     367           2 :         gd_utf8_terminated = data_blob_talloc(tctx, NULL, gd_utf8.length + 1);
     368           4 :         memcpy(gd_utf8_terminated.data, gd_utf8.data, gd_utf8.length);
     369           2 :         gd_utf8_terminated.data[gd_utf8.length] = '\0';
     370             : 
     371           2 :         gd_cp850_terminated = data_blob_talloc(tctx, NULL, gd_cp850.length + 1);
     372           4 :         memcpy(gd_cp850_terminated.data, gd_cp850.data, gd_cp850.length);
     373           2 :         gd_cp850_terminated.data[gd_cp850.length] = '\0';
     374             : 
     375           2 :         gd_utf16le_terminated = data_blob_talloc(tctx, NULL, gd_utf16le.length + 2);
     376           4 :         memcpy(gd_utf16le_terminated.data, gd_utf16le.data, gd_utf16le.length);
     377           2 :         gd_utf16le_terminated.data[gd_utf16le.length] = '\0';
     378           2 :         gd_utf16le_terminated.data[gd_utf16le.length + 1] = '\0';
     379             : 
     380           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     381             : 
     382           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     383             :                                                           CH_UTF8, CH_UTF16LE,
     384             :                                                           gd_utf8_terminated.data, -1,
     385             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     386             :                        "conversion from UTF8 to UTF16LE null terminated");
     387           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated");
     388             : 
     389           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     390           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     391             :                                                           CH_UTF8, CH_UTF16LE,
     392             :                                                           gd_utf8_terminated.data, -1,
     393             :                                                           (void *)gd_output.data, gd_utf16le.length, &gd_output.length) == false,
     394             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     395           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     396           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion from UTF8 to UTF16LE null terminated");
     397             : 
     398           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     399           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     400             :                                                           CH_UTF8, CH_UTF16LE,
     401             :                                                           gd_utf8_terminated.data, -1,
     402             :                                                           (void *)gd_output.data, gd_utf16le.length - 1, &gd_output.length) == false,
     403             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     404           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     405             : 
     406           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     407           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     408             :                                                           CH_UTF8, CH_UTF16LE,
     409             :                                                           gd_utf8_terminated.data, -1,
     410             :                                                           (void *)gd_output.data, gd_utf16le.length - 2, &gd_output.length) == false,
     411             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     412           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     413             : 
     414           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
     415           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     416             :                                                          CH_UTF16LE, CH_UTF8,
     417             :                                                          gd_utf16le_terminated.data, -1,
     418             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     419             :                        "conversion from UTF16LE to UTF8 null terminated");
     420           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated");
     421             : 
     422           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
     423             : 
     424           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     425             :                                                          CH_UTF16LE, CH_UTF8,
     426             :                                                          gd_utf16le_terminated.data, -1,
     427             :                                                          (void *)gd_output.data, gd_utf8.length, &gd_output.length) == false,
     428             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     429           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     430           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 null terminated");
     431             : 
     432           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
     433             : 
     434           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     435             :                                                          CH_UTF16LE, CH_UTF8,
     436             :                                                          gd_utf16le_terminated.data, -1,
     437             :                                                          (void *)gd_output.data, gd_utf8.length - 1, &gd_output.length) == false,
     438             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     439           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     440             : 
     441           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
     442             : 
     443           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     444             :                                                          CH_UTF16LE, CH_UTF8,
     445             :                                                          gd_utf16le_terminated.data, -1,
     446             :                                                          (void *)gd_output.data, gd_utf8.length - 2, &gd_output.length) == false,
     447             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     448           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     449             : 
     450           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10);
     451             : 
     452           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     453             :                                                          CH_UTF16LE, CH_DOS,
     454             :                                                          gd_utf16le_terminated.data, -1,
     455             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     456             :                        "conversion from UTF16LE to CP850 (dos) null terminated");
     457           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, "conversion from UTF16LE to CP850 (dos) null terminated");
     458             : 
     459             :         /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */
     460           2 :         gd_utf8_terminated.data[3] = '\0';
     461           2 :         gd_utf8_terminated.length = 4; /* used for the comparison only */
     462             : 
     463           2 :         gd_cp850_terminated.data[2] = '\0';
     464           2 :         gd_cp850_terminated.length = 3; /* used for the comparison only */
     465             : 
     466           2 :         gd_utf16le_terminated.data[4] = '\0';
     467           2 :         gd_utf16le_terminated.data[5] = '\0';
     468           2 :         gd_utf16le_terminated.length = 6; /* used for the comparison only */
     469             : 
     470           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     471             : 
     472           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     473             :                                                           CH_UTF8, CH_UTF16LE,
     474             :                                                           gd_utf8_terminated.data, -1,
     475             :                                                           (void *)gd_output.data, gd_output.length, &gd_output.length),
     476             :                        "conversion from UTF8 to UTF16LE null terminated");
     477           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
     478             : 
     479           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
     480             : 
     481           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     482             :                                                           CH_UTF16LE, CH_UTF8,
     483             :                                                           gd_utf16le_terminated.data, -1,
     484             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     485             :                        "conversion from UTF16LE to UTF8 null terminated");
     486           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early");
     487             : 
     488           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     489             : 
     490           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     491             :                                                           CH_DOS, CH_UTF16LE,
     492             :                                                           gd_cp850_terminated.data, -1,
     493             :                                                           (void *)gd_output.data, gd_output.length, &gd_output.length),
     494             :                        "conversion from CP850 to UTF16LE null terminated");
     495           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
     496             : 
     497           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10);
     498             : 
     499           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     500             :                                                           CH_UTF16LE, CH_DOS,
     501             :                                                           gd_utf16le_terminated.data, -1,
     502             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     503             :                        "conversion from UTF16LE to UTF8 null terminated");
     504           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, "conversion from UTF16LE to UTF8 null terminated early");
     505             :         
     506             :         /* Now null terminate the string particularly early, the confirm we don't skip the NULL and convert any further */
     507           2 :         gd_utf8_terminated.data[1] = '\0';
     508           2 :         gd_utf8_terminated.length = 2; /* used for the comparison only */
     509             :         
     510           2 :         gd_utf16le_terminated.data[2] = '\0';
     511           2 :         gd_utf16le_terminated.data[3] = '\0';
     512           2 :         gd_utf16le_terminated.length = 4; /* used for the comparison only */
     513             : 
     514           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
     515             : 
     516           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, CH_UTF16LE,
     517             :                                                           gd_utf8_terminated.data, -1,
     518             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     519             :                        "conversion from UTF8 to UTF16LE null terminated");
     520           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated very early");
     521             : 
     522           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
     523             : 
     524           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     525             :                                                           CH_UTF16LE, CH_UTF8,
     526             :                                                           gd_utf16le_terminated.data, -1,
     527             :                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
     528             :                        "conversion from UTF16LE to UTF8 null terminated");
     529           2 :         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated very early");
     530             : 
     531           0 :         return true;
     532             : }
     533             : 
     534           2 : static bool test_gd_ascii_handle(struct torture_context *tctx)
     535             : {
     536             :         struct smb_iconv_handle *iconv_handle;
     537           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
     538           2 :         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
     539           2 :         DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64);
     540           2 :         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
     541             :         DATA_BLOB gd_output;
     542             : 
     543           2 :         talloc_steal(tctx, gd_utf8.data);
     544           2 :         talloc_steal(tctx, gd_cp850.data);
     545           2 :         talloc_steal(tctx, gd_iso8859_1.data);
     546           2 :         talloc_steal(tctx, gd_utf16le.data);
     547             : 
     548           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8", 
     549           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     550           2 :         torture_assert(tctx, iconv_handle, "getting iconv handle");
     551             : 
     552           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
     553             :                                                     CH_UTF8, CH_DOS,
     554             :                                                     gd_utf8.data, gd_utf8.length,
     555             :                                                     (void *)&gd_output.data, &gd_output.length) == false,
     556             :                        "conversion from UTF8 to (dos charset) ASCII should fail");
     557             : 
     558           2 :         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length);
     559             : 
     560           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     561             :                                                          CH_UTF8, CH_DOS,
     562             :                                                          gd_utf8.data, gd_utf8.length,
     563             :                                                          (void *)gd_output.data, gd_output.length,
     564             :                                                          &gd_output.length) == false,
     565             :                        "conversion from UTF8 to (dos charset) ASCII should fail");
     566           2 :         torture_assert_errno_equal(tctx, EILSEQ, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail E2BIG");
     567           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     568           2 :         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "partial conversion from UTF8 to (dos charset) ASCII incorrect");
     569             : 
     570             :         /* Short output handling confirmation */
     571           2 :         gd_output.length = 1;
     572           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     573             :                                                          CH_UTF8, CH_DOS,
     574             :                                                          gd_utf8.data, gd_utf8.length,
     575             :                                                          (void *)gd_output.data, gd_output.length,
     576             :                                                          &gd_output.length) == false,
     577             :                        "conversion from UTF8 to (dos charset) ASCII should fail due to too short");
     578           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ASCII too short");
     579           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     580           2 :         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to (dos charset) ASCII incorrect");
     581             : 
     582             :         /* Short output handling confirmation */
     583           2 :         gd_output.length = 2;
     584           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     585             :                                                          CH_UTF8, CH_DOS,
     586             :                                                          gd_utf8.data, gd_utf8.length,
     587             :                                                          (void *)gd_output.data, gd_output.length,
     588             :                                                          &gd_output.length) == false,
     589             :                        "conversion from UTF8 to (dos charset) ASCII should fail due to too illigal seqence");
     590           2 :         torture_assert_errno_equal(tctx, EILSEQ, "conversion from UTF8 to (dos charset) ISO-8859-1 should fail EILSEQ");
     591           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 2 char of output");
     592             : 
     593             :         /* Short input handling confirmation */
     594           2 :         gd_output.length = gd_utf8.length;
     595           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     596             :                                                          CH_UTF8, CH_DOS,
     597             :                                                          gd_utf8.data, 2,
     598             :                                                          (void *)gd_output.data, gd_output.length,
     599             :                                                          &gd_output.length) == false,
     600             :                        "conversion from UTF8 to (dos charset) ASCII should fail due to too short");
     601           2 :         torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to (dos charset) ASCII should fail EILSEQ");
     602           1 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
     603           0 :         return true;
     604             : }
     605             : 
     606           2 : static bool test_plato_english_iso8859_cp850_handle(struct torture_context *tctx)
     607             : {
     608             :         struct smb_iconv_handle *iconv_handle;
     609           2 :         DATA_BLOB plato_english_utf8 = data_blob_string_const(plato_english_ascii);
     610           2 :         DATA_BLOB plato_english_cp850 = plato_english_utf8;
     611           2 :         DATA_BLOB plato_english_iso8859_1 = plato_english_utf8;
     612           2 :         DATA_BLOB plato_english_utf16le = base64_decode_data_blob(plato_english_utf16le_base64);
     613             :         DATA_BLOB plato_english_output;
     614             :         DATA_BLOB plato_english_output2;
     615             :         
     616           2 :         talloc_steal(tctx, plato_english_utf16le.data);
     617             : 
     618           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850", 
     619           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     620           2 :         torture_assert(tctx, iconv_handle, "getting iconv handle");
     621             :                 
     622           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     623             :                                                     CH_UTF8, CH_DOS, 
     624             :                                                     plato_english_utf8.data, plato_english_utf8.length, 
     625             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     626             :                        "conversion from UTF8 to (dos charset) ISO-8859-1");
     627           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF8 to (dos charset) ISO-8859-1 incorrect");
     628             :         
     629           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     630             :                                                     CH_UTF8, CH_UNIX, 
     631             :                                                     plato_english_utf8.data, plato_english_utf8.length, 
     632             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     633             :                        "conversion from UTF8 to (unix charset) CP850");
     634           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF8 to (unix charset) CP850 incorrect");
     635             :         
     636           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     637             :                                                     CH_UTF8, CH_UTF8, 
     638             :                                                     plato_english_utf8.data, plato_english_utf8.length, 
     639             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     640             :                        "conversion from UTF8 to UTF8");
     641           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF8 to UTF8 incorrect");
     642             :         
     643           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     644             :                                                     CH_UTF16LE, CH_DOS, 
     645             :                                                     plato_english_utf16le.data, plato_english_utf16le.length, 
     646             :                                                     (void *)&plato_english_output.data, &plato_english_output.length),
     647             :                        "conversion from UTF16LE to (dos charset) ISO-8859-1");
     648           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect");
     649             :         
     650           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     651             :                                                     CH_DOS, CH_UTF16LE, 
     652             :                                                     plato_english_output.data, plato_english_output.length, 
     653             :                                                     (void *)&plato_english_output2.data, &plato_english_output2.length),
     654             :                        "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE");
     655           2 :         torture_assert_data_blob_equal(tctx, plato_english_output2, plato_english_utf16le,  "round trip conversion from (dos charset) ISO-8859-1 back to UTF16LE");
     656             :         
     657           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     658             :                                                     CH_UTF16LE, CH_UTF8,
     659             :                                                     plato_english_utf16le.data, plato_english_utf16le.length,
     660             :                                                     (void *)&plato_english_output.data, &plato_english_output.length),
     661             :                        "conversion from UTF16LE to UTF8");
     662           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
     663             : 
     664           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     665             :                                                          CH_UTF16LE, CH_UTF8,
     666             :                                                          plato_english_utf16le.data, plato_english_utf16le.length,
     667             :                                                          (void *)plato_english_output.data, plato_english_output.length,
     668             :                                                          &plato_english_output.length),
     669             :                        "conversion from UTF16LE to UTF8");
     670           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
     671             : 
     672           2 :         plato_english_output.length = 5;
     673           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     674             :                                                          CH_UTF16LE, CH_UTF8,
     675             :                                                          plato_english_utf16le.data, plato_english_utf16le.length,
     676             :                                                          (void *)plato_english_output.data, plato_english_output.length,
     677             :                                                          &plato_english_output.length) == false,
     678             :                        "conversion from UTF16LE to UTF8 should fail due to short output");
     679           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, data_blob_string_const("What "), "conversion from UTF16LE to UTF8 incorrect");
     680           2 :         torture_assert_int_equal(tctx, plato_english_output.length, 5, "short conversion failed");
     681             : 
     682           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
     683             :                                                     CH_UTF16LE, CH_UNIX, 
     684             :                                                     plato_english_utf16le.data, plato_english_utf16le.length, 
     685             :                                                     (void *)&plato_english_output.data, &plato_english_output.length),
     686             :                        "conversion from UTF16LE to (unix charset) CP850");
     687           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
     688             :         
     689           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     690             :                                                     CH_UTF16LE, CH_UTF8, 
     691             :                                                     plato_english_utf16le.data, plato_english_utf16le.length, 
     692             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     693             :                        "conversion from UTF16LE to UTF8");
     694           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
     695             :         
     696           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     697             :                                                     CH_DOS, CH_DOS, 
     698             :                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
     699             :                                                     (void *)&plato_english_output.data, &plato_english_output.length),
     700             :                        "conversion from (dos charset) ISO-8859-1 to (dos charset) ISO-8859-1");
     701           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF16LE to (dos charset) ISO-8859-1 incorrect");
     702             :         
     703           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     704             :                                                     CH_DOS, CH_UNIX, 
     705             :                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
     706             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     707             :                        "conversion from (dos charset) ISO-8859-1 to (unix charset) CP850");
     708           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
     709             :         
     710           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     711             :                                                     CH_DOS, CH_UTF8, 
     712             :                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
     713             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     714             :                        "conversion from (dos charset) ISO-8859-1 to UTF8");
     715           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
     716             : 
     717           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     718             :                                                     CH_DOS, CH_UTF16LE, 
     719             :                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
     720             :                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
     721             :                        "conversion from (dos charset) ISO-8859-1 to UTF16LE");
     722           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le, "conversion from (dos charset) ISO-8859-1 to UTF16LE");
     723           0 :         return true;
     724             : }
     725             : 
     726           2 : static bool test_plato_english_minus_1_handle(struct torture_context *tctx)
     727             : {
     728             :         struct smb_iconv_handle *iconv_handle;
     729           2 :         DATA_BLOB plato_english_utf8 = data_blob_string_const(plato_english_ascii);
     730           2 :         DATA_BLOB plato_english_utf16le = base64_decode_data_blob(plato_english_utf16le_base64);
     731             :         DATA_BLOB plato_english_output;
     732             :         DATA_BLOB plato_english_utf8_terminated;
     733             :         DATA_BLOB plato_english_utf16le_terminated;
     734             :         
     735           2 :         talloc_steal(tctx, plato_english_utf16le.data);
     736             : 
     737           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850", 
     738           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     739           2 :         torture_assert(tctx, iconv_handle, "getting iconv handle");
     740             : 
     741           2 :         plato_english_utf8_terminated = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 1);
     742           4 :         memcpy(plato_english_utf8_terminated.data, plato_english_utf8.data, plato_english_utf8.length);
     743           2 :         plato_english_utf8_terminated.data[plato_english_utf8.length] = '\0';
     744             : 
     745           2 :         plato_english_utf16le_terminated = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 2);
     746           4 :         memcpy(plato_english_utf16le_terminated.data, plato_english_utf16le.data, plato_english_utf16le.length);
     747           2 :         plato_english_utf16le_terminated.data[plato_english_utf16le.length] = '\0';
     748           2 :         plato_english_utf16le_terminated.data[plato_english_utf16le.length + 1] = '\0';
     749             :                 
     750           2 :         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10);
     751             : 
     752           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     753             :                                                           CH_UTF8, CH_UTF16LE,
     754             :                                                           plato_english_utf8_terminated.data, -1,
     755             :                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
     756             :                        "conversion from UTF8 to UTF16LE null terminated");
     757           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated");
     758             : 
     759           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     760             :                                                           CH_UTF8, CH_UTF16LE,
     761             :                                                           plato_english_utf8_terminated.data, -1,
     762             :                                                           (void *)plato_english_output.data, plato_english_utf16le.length, &plato_english_output.length) == false,
     763             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     764           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     765           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le, "conversion from UTF8 to UTF16LE null terminated");
     766             : 
     767           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     768             :                                                           CH_UTF8, CH_UTF16LE,
     769             :                                                           plato_english_utf8_terminated.data, -1,
     770             :                                                           (void *)plato_english_output.data, plato_english_utf16le.length - 1, &plato_english_output.length) == false,
     771             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     772           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     773             : 
     774           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     775             :                                                           CH_UTF8, CH_UTF16LE,
     776             :                                                           plato_english_utf8_terminated.data, -1,
     777             :                                                           (void *)plato_english_output.data, plato_english_utf16le.length - 2, &plato_english_output.length) == false,
     778             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     779           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     780             : 
     781           2 :         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10);
     782             : 
     783           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     784             :                                                          CH_UTF16LE, CH_UTF8,
     785             :                                                          plato_english_utf16le_terminated.data, -1,
     786             :                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
     787             :                        "conversion from UTF16LE to UTF8 null terminated");
     788           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated");
     789             : 
     790           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     791             :                                                          CH_UTF16LE, CH_UTF8,
     792             :                                                          plato_english_utf16le_terminated.data, -1,
     793             :                                                          (void *)plato_english_output.data, plato_english_utf8.length, &plato_english_output.length) == false,
     794             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     795           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     796           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 null terminated");
     797             : 
     798           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     799             :                                                          CH_UTF16LE, CH_UTF8,
     800             :                                                          plato_english_utf16le_terminated.data, -1,
     801             :                                                          (void *)plato_english_output.data, plato_english_utf8.length - 1, &plato_english_output.length) == false,
     802             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     803           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     804             : 
     805           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     806             :                                                          CH_UTF16LE, CH_UTF8,
     807             :                                                          plato_english_utf16le_terminated.data, -1,
     808             :                                                          (void *)plato_english_output.data, plato_english_utf8.length - 2, &plato_english_output.length) == false,
     809             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     810           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     811             : 
     812             :         /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */
     813           2 :         plato_english_utf8_terminated.data[3] = '\0';
     814           2 :         plato_english_utf8_terminated.length = 4; /* used for the comparison only */
     815             : 
     816           2 :         plato_english_utf16le_terminated.data[6] = '\0';
     817           2 :         plato_english_utf16le_terminated.data[7] = '\0';
     818           2 :         plato_english_utf16le_terminated.length = 8; /* used for the comparison only */
     819             : 
     820           2 :         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10);
     821             : 
     822           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     823             :                                                           CH_UTF8, CH_UTF16LE,
     824             :                                                           plato_english_utf8_terminated.data, -1,
     825             :                                                           (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
     826             :                        "conversion from UTF8 to UTF16LE null terminated");
     827           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
     828             : 
     829           2 :         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10);
     830             : 
     831           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     832             :                                                           CH_UTF16LE, CH_UTF8,
     833             :                                                           plato_english_utf16le_terminated.data, -1,
     834             :                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
     835             :                        "conversion from UTF16LE to UTF8 null terminated");
     836           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early");
     837             : 
     838             :         
     839             :         /* Now null terminate the string particularly early, the confirm we don't skip the NULL and convert any further */
     840           2 :         plato_english_utf8_terminated.data[1] = '\0';
     841           2 :         plato_english_utf8_terminated.length = 2; /* used for the comparison only */
     842             :         
     843           2 :         plato_english_utf16le_terminated.data[2] = '\0';
     844           2 :         plato_english_utf16le_terminated.data[3] = '\0';
     845           2 :         plato_english_utf16le_terminated.length = 4; /* used for the comparison only */
     846             : 
     847           2 :         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10);
     848             : 
     849           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, CH_UTF16LE,
     850             :                                                           plato_english_utf8_terminated.data, -1,
     851             :                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
     852             :                        "conversion from UTF8 to UTF16LE null terminated");
     853           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated very early");
     854             : 
     855           2 :         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10);
     856             : 
     857           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     858             :                                                           CH_UTF16LE, CH_UTF8,
     859             :                                                           plato_english_utf16le_terminated.data, -1,
     860             :                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
     861             :                        "conversion from UTF16LE to UTF8 null terminated");
     862           2 :         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated very early");
     863             : 
     864           0 :         return true;
     865             : }
     866             : 
     867           2 : static bool test_plato_minus_1_handle(struct torture_context *tctx)
     868             : {
     869             :         struct smb_iconv_handle *iconv_handle;
     870           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
     871           2 :         DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64);
     872             :         DATA_BLOB plato_output;
     873             :         DATA_BLOB plato_utf8_terminated;
     874             :         DATA_BLOB plato_utf16le_terminated;
     875             :         
     876           2 :         talloc_steal(tctx, plato_utf8.data);
     877           2 :         talloc_steal(tctx, plato_utf16le.data);
     878             : 
     879           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ISO-8859-1", "CP850",
     880           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     881           2 :         torture_assert(tctx, iconv_handle, "getting iconv handle");
     882             : 
     883           2 :         plato_utf8_terminated = data_blob_talloc(tctx, NULL, plato_utf8.length + 1);
     884           4 :         memcpy(plato_utf8_terminated.data, plato_utf8.data, plato_utf8.length);
     885           2 :         plato_utf8_terminated.data[plato_utf8.length] = '\0';
     886             : 
     887           2 :         plato_utf16le_terminated = data_blob_talloc(tctx, NULL, plato_utf16le.length + 2);
     888           4 :         memcpy(plato_utf16le_terminated.data, plato_utf16le.data, plato_utf16le.length);
     889           2 :         plato_utf16le_terminated.data[plato_utf16le.length] = '\0';
     890           2 :         plato_utf16le_terminated.data[plato_utf16le.length + 1] = '\0';
     891             : 
     892           2 :         plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length + 10);
     893             : 
     894           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     895             :                                                           CH_UTF8, CH_UTF16LE,
     896             :                                                           plato_utf8_terminated.data, -1,
     897             :                                                          (void *)plato_output.data, plato_output.length, &plato_output.length),
     898             :                        "conversion from UTF8 to UTF16LE null terminated");
     899           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated");
     900             : 
     901           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     902             :                                                           CH_UTF8, CH_UTF16LE,
     903             :                                                           plato_utf8_terminated.data, -1,
     904             :                                                           (void *)plato_output.data, plato_utf16le.length, &plato_output.length) == false,
     905             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     906           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     907           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE null terminated");
     908             : 
     909           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     910             :                                                           CH_UTF8, CH_UTF16LE,
     911             :                                                           plato_utf8_terminated.data, -1,
     912             :                                                           (void *)plato_output.data, plato_utf16le.length - 1, &plato_output.length) == false,
     913             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     914           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     915             : 
     916           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     917             :                                                           CH_UTF8, CH_UTF16LE,
     918             :                                                           plato_utf8_terminated.data, -1,
     919             :                                                           (void *)plato_output.data, plato_utf16le.length - 2, &plato_output.length) == false,
     920             :                        "conversion from UTF8 to UTF16LE null terminated should fail");
     921           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
     922             : 
     923           2 :         plato_output = data_blob_talloc(tctx, NULL, plato_utf8.length + 10);
     924             : 
     925           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     926             :                                                          CH_UTF16LE, CH_UTF8,
     927             :                                                          plato_utf16le_terminated.data, -1,
     928             :                                                          (void *)plato_output.data, plato_output.length, &plato_output.length),
     929             :                        "conversion from UTF16LE to UTF8 null terminated");
     930           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated");
     931             : 
     932           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     933             :                                                          CH_UTF16LE, CH_UTF8,
     934             :                                                          plato_utf16le_terminated.data, -1,
     935             :                                                          (void *)plato_output.data, plato_utf8.length, &plato_output.length) == false,
     936             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     937           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     938           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 null terminated");
     939             : 
     940           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     941             :                                                          CH_UTF16LE, CH_UTF8,
     942             :                                                          plato_utf16le_terminated.data, -1,
     943             :                                                          (void *)plato_output.data, plato_utf8.length - 1, &plato_output.length) == false,
     944             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     945           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     946             : 
     947           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     948             :                                                          CH_UTF16LE, CH_UTF8,
     949             :                                                          plato_utf16le_terminated.data, -1,
     950             :                                                          (void *)plato_output.data, plato_utf8.length - 2, &plato_output.length) == false,
     951             :                        "conversion from UTF16LE to UTF8 null terminated should fail");
     952           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
     953             : 
     954             :         /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */
     955           2 :         plato_utf8_terminated.data[5] = '\0';
     956           2 :         plato_utf8_terminated.length = 6; /* used for the comparison only */
     957             : 
     958           2 :         plato_utf16le_terminated.data[4] = '\0';
     959           2 :         plato_utf16le_terminated.data[5] = '\0';
     960           2 :         plato_utf16le_terminated.length = 6; /* used for the comparison only */
     961             : 
     962           2 :         plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length + 10);
     963             : 
     964           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     965             :                                                           CH_UTF8, CH_UTF16LE,
     966             :                                                           plato_utf8_terminated.data, -1,
     967             :                                                           (void *)plato_output.data, plato_output.length, &plato_output.length),
     968             :                        "conversion from UTF8 to UTF16LE null terminated");
     969           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
     970             : 
     971           2 :         plato_output = data_blob_talloc(tctx, NULL, plato_utf8.length + 10);
     972             : 
     973           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
     974             :                                                           CH_UTF16LE, CH_UTF8,
     975             :                                                           plato_utf16le_terminated.data, -1,
     976             :                                                          (void *)plato_output.data, plato_output.length, &plato_output.length),
     977             :                        "conversion from UTF16LE to UTF8 null terminated");
     978           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early");
     979             :         
     980           0 :         return true;
     981             : }
     982             : 
     983           2 : static bool test_plato_cp850_utf8_handle(struct torture_context *tctx)
     984             : {
     985             :         struct smb_iconv_handle *iconv_handle;
     986           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
     987           2 :         DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64);
     988             :         DATA_BLOB plato_output;
     989             :         DATA_BLOB plato_output2;
     990             :         
     991           2 :         talloc_steal(tctx, plato_utf8.data);
     992           2 :         talloc_steal(tctx, plato_utf16le.data);
     993             : 
     994           2 :         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8", 
     995           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
     996           2 :         torture_assert(tctx, iconv_handle, "creating iconv handle");
     997             :                 
     998           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
     999             :                                                     CH_UTF8, CH_UTF16LE,
    1000             :                                                     plato_utf8.data, plato_utf8.length,
    1001             :                                                     (void *)&plato_output.data, &plato_output.length),
    1002             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1003           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
    1004             : 
    1005           2 :         torture_assert_int_equal(tctx,
    1006             :                                  strlen_m_ext_handle(iconv_handle,
    1007             :                                                      (const char *)plato_utf8.data,
    1008             :                                                      CH_UTF8, CH_UTF16LE),
    1009             :                                  plato_output.length / 2,
    1010             :                                  "checking strlen_m_ext of conversion of UTF8 to UTF16LE");
    1011             : 
    1012           4 :         memset(plato_output.data, '\0', plato_output.length);
    1013           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1014             :                                                          CH_UTF8, CH_UTF16LE,
    1015             :                                                          plato_utf8.data, plato_utf8.length,
    1016             :                                                          (void *)plato_output.data, plato_output.length,
    1017             :                                                          &plato_output.length),
    1018             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1019           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
    1020             : 
    1021           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
    1022             :                                                     CH_UTF16LE, CH_UTF8,
    1023             :                                                     plato_output.data, plato_output.length,
    1024             :                                                     (void *)&plato_output2.data, &plato_output2.length),
    1025             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1026           2 :         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
    1027             : 
    1028           4 :         memset(plato_output2.data, '\0', plato_output2.length);
    1029           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1030             :                                                    CH_UTF16LE, CH_UTF8,
    1031             :                                                    plato_output.data, plato_output.length,
    1032             :                                                    (void *)plato_output2.data, plato_output2.length, &plato_output2.length),
    1033             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1034           2 :         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
    1035             : 
    1036           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
    1037             :                                                           CH_UTF8, CH_UTF8,
    1038             :                                                           plato_utf8.data, plato_utf8.length,
    1039             :                                                           (void *)&plato_output.data, &plato_output.length),
    1040             :                        "conversion of UTF8 to UTF8");
    1041           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8,
    1042             :                                        "conversion of UTF8 to UTF8");
    1043           2 :         torture_assert_int_equal(tctx,
    1044             :                                  strlen_m_ext_handle(iconv_handle,
    1045             :                                                      (const char *)plato_utf8.data,
    1046             :                                                      CH_UTF8, CH_UTF8),
    1047             :                                  plato_output.length,
    1048             :                                  "checking strlen_m_ext of conversion of UTF8 to UTF8");
    1049           4 :         memset(plato_output.data, '\0', plato_output.length);
    1050           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1051             :                                                          CH_UTF8, CH_UTF8,
    1052             :                                                          plato_utf8.data, plato_utf8.length,
    1053             :                                                          (void *)plato_output.data, plato_output.length,
    1054             :                                                          &plato_output.length),
    1055             :                        "conversion of UTF8 to UTF8");
    1056             : 
    1057           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
    1058             :                                                     CH_UTF8, CH_DOS, 
    1059             :                                                     plato_utf8.data, plato_utf8.length, 
    1060             :                                                     (void *)&plato_output.data, &plato_output.length) == false, 
    1061             :                        "conversion of UTF8 ancient greek to DOS charset CP850 should fail");
    1062             :         
    1063           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1064             :                                                     CH_UTF8, CH_UNIX, 
    1065             :                                                     plato_utf8.data, plato_utf8.length, 
    1066             :                                                     (void *)&plato_output.data, &plato_output.length),
    1067             :                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
    1068           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect");
    1069             :         
    1070           4 :         memset(plato_output.data, '\0', plato_output.length);
    1071           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1072             :                                                          CH_UTF8, CH_UNIX,
    1073             :                                                          plato_utf8.data, plato_utf8.length,
    1074             :                                                          (void *)plato_output.data, plato_output.length,
    1075             :                                                          &plato_output.length),
    1076             :                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
    1077           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect");
    1078             : 
    1079           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1080             :                                                     CH_UTF8, CH_UTF8, 
    1081             :                                                     plato_utf8.data, plato_utf8.length, 
    1082             :                                                     (void *)&plato_output.data, &plato_output.length),
    1083             :                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
    1084           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to UTF8 incorrect");
    1085             :         
    1086           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1087             :                                                     CH_UTF16LE, CH_DOS, 
    1088             :                                                     plato_utf16le.data, plato_utf16le.length, 
    1089             :                                                     (void *)&plato_output.data, &plato_output.length) == false,         
    1090             :                        "conversion of UTF16 ancient greek to DOS charset CP850 should fail");
    1091             : 
    1092             :         /* Allocate enough space, if it were possible do do the conversion */
    1093           2 :         plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length);
    1094           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1095             :                                                          CH_UTF16LE, CH_DOS,
    1096             :                                                          plato_utf16le.data, plato_utf16le.length,
    1097             :                                                          (void *)plato_output.data, plato_output.length,
    1098             :                                                          &plato_output.length) == false,
    1099             :                        "conversion of UTF16 ancient greek to DOS charset CP850 should fail");
    1100           2 :         torture_assert_errno_equal(tctx,  EILSEQ, "conversion of UTF16 ancient greek to DOS charset CP850 should fail");
    1101             : 
    1102             :         /* Allocate only enough space for a partial conversion */
    1103           2 :         plato_output = data_blob_talloc(tctx, NULL, 9);
    1104           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1105             :                                                          CH_UTF16LE, CH_UTF8,
    1106             :                                                          plato_utf16le.data, plato_utf16le.length,
    1107             :                                                          (void *)plato_output.data, plato_output.length,
    1108             :                                                          &plato_output.length) == false,
    1109             :                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1110           2 :         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1111           2 :         torture_assert_int_equal(tctx, plato_output.length, 8,
    1112             :                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
    1113             : 
    1114           2 :         plato_output = data_blob_talloc(tctx, NULL, 2);
    1115           2 :         torture_assert(tctx, convert_string_error_handle(iconv_handle,
    1116             :                                                          CH_UTF16LE, CH_UTF8,
    1117             :                                                          plato_utf16le.data, plato_utf16le.length,
    1118             :                                                          (void *)plato_output.data, plato_output.length,
    1119             :                                                          &plato_output.length) == false,
    1120             :                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1121           2 :         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1122           2 :         torture_assert_int_equal(tctx, plato_output.length, 0,
    1123             :                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
    1124             : 
    1125             : 
    1126           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1127             :                                                     CH_UTF16LE, CH_UNIX, 
    1128             :                                                     plato_utf16le.data, plato_utf16le.length, 
    1129             :                                                     (void *)&plato_output.data, &plato_output.length),  
    1130             :                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
    1131           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to (unix charset) UTF8 incorrect");
    1132           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
    1133             :                                                     CH_UTF16LE, CH_UTF8,
    1134             :                                                     plato_utf16le.data, plato_utf16le.length,
    1135             :                                                     (void *)&plato_output.data, &plato_output.length),
    1136             :                        "conversion of UTF16 ancient greek to UTF8 failed");
    1137           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 incorrect");
    1138           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1139             :                                                           CH_UTF16LE, CH_UTF8, 
    1140             :                                                           plato_utf16le.data, plato_utf16le.length, 
    1141             :                                                           (void *)&plato_output.data, &plato_output.length),
    1142             :                        "conversion of UTF16 ancient greek to UTF8 failed");
    1143           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 incorrect");
    1144             :         
    1145           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1146             :                                                           CH_UTF8, CH_UTF16LE, 
    1147             :                                                           plato_output.data, plato_output.length, 
    1148             :                                                           (void *)&plato_output2.data, &plato_output2.length),
    1149             :                        "round trip conversion of UTF16 ancient greek to UTF8 and back again failed");
    1150           2 :         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf16le,
    1151             :                                        "round trip conversion of UTF16 ancient greek to UTF8 and back again failed");
    1152           2 :         torture_assert_int_equal(tctx,
    1153             :                                  strlen_m_ext_handle(iconv_handle,
    1154             :                                                      (const char *)plato_output.data,
    1155             :                                                      CH_UTF8, CH_UTF16LE),
    1156             :                                  plato_output2.length / 2,
    1157             :                                  "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again");
    1158             : 
    1159           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
    1160             :                                                           CH_UTF8, CH_UTF8,
    1161             :                                                           plato_output.data, plato_output.length,
    1162             :                                                           (void *)&plato_output2.data, &plato_output2.length),
    1163             :                        "conversion of UTF8 to UTF8");
    1164           2 :         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8,
    1165             :                                        "conversion of UTF8 to UTF8");
    1166           2 :         torture_assert_int_equal(tctx,
    1167             :                                  strlen_m_ext_handle(iconv_handle,
    1168             :                                                      (const char *)plato_output.data,
    1169             :                                                      CH_UTF8, CH_UTF8),
    1170             :                                  plato_output2.length,
    1171             :                                  "checking strlen_m_ext of conversion of UTF8 to UTF8");
    1172           0 :         return true;
    1173             : }
    1174             : 
    1175           2 : static bool test_plato_latin_cp850_utf8_handle(struct torture_context *tctx)
    1176             : {
    1177             :         struct smb_iconv_handle *iconv_handle;
    1178           2 :         DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64);
    1179           2 :         DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64);
    1180             :         DATA_BLOB plato_latin_output;
    1181             :         DATA_BLOB plato_latin_output2;
    1182             :         
    1183           2 :         talloc_steal(tctx, plato_latin_utf8.data);
    1184           2 :         talloc_steal(tctx, plato_latin_utf16le.data);
    1185             : 
    1186           2 :         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8",
    1187           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
    1188           2 :         torture_assert(tctx, iconv_handle, "creating iconv handle");
    1189             :                 
    1190           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1191             :                                                     CH_UTF8, CH_DOS, 
    1192             :                                                     plato_latin_utf8.data, plato_latin_utf8.length, 
    1193             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length) == false, 
    1194             :                        "conversion of UTF8  latin charset greek to DOS charset CP850 should fail");
    1195             :         
    1196           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1197             :                                                     CH_UTF8, CH_UNIX, 
    1198             :                                                     plato_latin_utf8.data, plato_latin_utf8.length, 
    1199             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
    1200             :                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
    1201           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect");
    1202             :         
    1203           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1204             :                                                     CH_UTF8, CH_UTF8, 
    1205             :                                                     plato_latin_utf8.data, plato_latin_utf8.length, 
    1206             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
    1207             :                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
    1208           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF8 to UTF8 incorrect");
    1209             :         
    1210           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1211             :                                                     CH_UTF16LE, CH_DOS, 
    1212             :                                                     plato_latin_utf16le.data, plato_latin_utf16le.length, 
    1213             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length) == false,     
    1214             :                        "conversion of UTF16 latin charset greek to DOS charset CP850 should fail");
    1215             :         
    1216           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1217             :                                                     CH_UTF16LE, CH_UNIX, 
    1218             :                                                     plato_latin_utf16le.data, plato_latin_utf16le.length, 
    1219             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),      
    1220             :                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
    1221           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16LE to (unix charset) CP850 incorrect");
    1222             :         
    1223           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1224             :                                                           CH_UTF16LE, CH_UTF8, 
    1225             :                                                           plato_latin_utf16le.data, plato_latin_utf16le.length, 
    1226             :                                                           (void *)&plato_latin_output.data, &plato_latin_output.length),
    1227             :                        "conversion of UTF16 latin charset greek to UTF8 failed");
    1228           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16LE to UTF8 incorrect");
    1229             :         
    1230           2 :         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
    1231             :                                                           CH_UTF8, CH_UTF16LE, 
    1232             :                                                           plato_latin_output.data, plato_latin_output.length, 
    1233             :                                                           (void *)&plato_latin_output2.data, &plato_latin_output2.length),
    1234             :                        "round trip conversion of UTF16 latin charset greek to UTF8 and back again failed");
    1235           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output2, plato_latin_utf16le,
    1236             :                                        "round trip conversion of UTF16 latin charset greek to UTF8 and back again failed");
    1237           2 :         torture_assert_int_equal(tctx,
    1238             :                                  strlen_m_ext_handle(iconv_handle,
    1239             :                                                      (const char *)plato_latin_output.data,
    1240             :                                                      CH_UTF8, CH_UTF16LE),
    1241             :                                  plato_latin_output2.length / 2,
    1242             :                                  "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again");
    1243           0 :         return true;
    1244             : }
    1245             : 
    1246           2 : static bool test_utf8_nfc_to_nfd_overflow(struct torture_context *tctx)
    1247             : {
    1248             :         smb_iconv_t ic;
    1249             :         DATA_BLOB utf8_nfc_blob;
    1250             :         DATA_BLOB utf8_nfd_blob;
    1251             :         DATA_BLOB src_blob;
    1252             :         DATA_BLOB blob;
    1253             :         size_t nconv;
    1254           2 :         const char *src = NULL;
    1255           2 :         char *dst = NULL;
    1256             :         size_t dst_left;
    1257             :         size_t srclen;
    1258           2 :         bool ret = true;
    1259             : 
    1260           2 :         ic = smb_iconv_open("UTF8-NFD", "UTF8-NFC");
    1261           2 :         torture_assert_goto(tctx, ic != (smb_iconv_t)-1, ret, done,
    1262             :                             "creating iconv handle\n");
    1263             : 
    1264           2 :         utf8_nfc_blob = base64_decode_data_blob_talloc(tctx, utf8_nfc_base64);
    1265           2 :         torture_assert_not_null_goto(tctx, utf8_nfc_blob.data, ret, done,
    1266             :                                      "OOM\n");
    1267             : 
    1268           2 :         utf8_nfd_blob = base64_decode_data_blob_talloc(tctx, utf8_nfd_base64);
    1269           2 :         torture_assert_not_null_goto(tctx, utf8_nfd_blob.data, ret, done,
    1270             :                                      "OOM\n");
    1271             : 
    1272           2 :         blob = data_blob_talloc_zero(tctx, 255);
    1273           2 :         torture_assert_not_null_goto(tctx, blob.data, ret, done, "OOM\n");
    1274             : 
    1275             :         /*
    1276             :          * Unfortunately the current implementation that performs the conversion
    1277             :          * (using libicu) returns EINVAL if the result buffer is too small, not
    1278             :          * E2BIG like iconv().
    1279             :          */
    1280             : 
    1281           2 :         src = "foo";
    1282           2 :         srclen = 3;
    1283           2 :         dst = (char *)blob.data;
    1284           2 :         dst_left = 0;
    1285           2 :         nconv = smb_iconv(ic,
    1286             :                           &src,
    1287             :                           &srclen,
    1288             :                           &dst,
    1289             :                           &dst_left);
    1290           2 :         torture_assert_int_equal_goto(tctx, nconv, -1, ret, done,
    1291             :                                       "smb_iconv failed\n");
    1292           2 :         torture_assert_errno_equal_goto(tctx, EINVAL, ret, done,
    1293             :                                         "Wrong errno\n");
    1294             : 
    1295           2 :         src = "foo";
    1296           2 :         srclen = 3;
    1297           2 :         dst = (char *)blob.data;
    1298           2 :         dst_left = 1;
    1299           2 :         nconv = smb_iconv(ic,
    1300             :                           &src,
    1301             :                           &srclen,
    1302             :                           &dst,
    1303             :                           &dst_left);
    1304           2 :         torture_assert_int_equal_goto(tctx, nconv, -1, ret, done,
    1305             :                                       "smb_iconv failed\n");
    1306           2 :         torture_assert_errno_equal_goto(tctx, EINVAL, ret, done,
    1307             :                                         "Wrong errno\n");
    1308             : 
    1309           2 :         src = "foo";
    1310           2 :         srclen = 3;
    1311           2 :         dst = (char *)blob.data;
    1312           2 :         dst_left = 2;
    1313           2 :         nconv = smb_iconv(ic,
    1314             :                           &src,
    1315             :                           &srclen,
    1316             :                           &dst,
    1317             :                           &dst_left);
    1318           2 :         torture_assert_int_equal_goto(tctx, nconv, -1, ret, done,
    1319             :                                       "smb_iconv failed\n");
    1320           2 :         torture_assert_errno_equal_goto(tctx, EINVAL, ret, done,
    1321             :                                         "Wrong errno\n");
    1322             : 
    1323           2 :         src_blob = data_blob_const("foo", 3);
    1324           2 :         src = (const char *)src_blob.data;
    1325           2 :         srclen = src_blob.length;
    1326           2 :         dst = (char *)blob.data;
    1327           2 :         dst_left = 3;
    1328           2 :         nconv = smb_iconv(ic,
    1329             :                           &src,
    1330             :                           &srclen,
    1331             :                           &dst,
    1332             :                           &dst_left);
    1333           2 :         torture_assert_int_equal_goto(tctx, nconv, 3, ret, done,
    1334             :                                       "smb_iconv failed\n");
    1335             : 
    1336           2 :         blob.length = nconv;
    1337           2 :         torture_assert_data_blob_equal(tctx,
    1338             :                                        src_blob,
    1339             :                                        blob,
    1340             :                                        "Conversion failed\n");
    1341             : 
    1342           2 :         src_blob = data_blob_const("foo", 4);
    1343           2 :         src = (const char *)src_blob.data;
    1344           2 :         srclen = src_blob.length;
    1345           2 :         dst = (char *)blob.data;
    1346           2 :         dst_left = 4;
    1347           2 :         nconv = smb_iconv(ic,
    1348             :                           &src,
    1349             :                           &srclen,
    1350             :                           &dst,
    1351             :                           &dst_left);
    1352           2 :         torture_assert_int_equal_goto(tctx, nconv, 4, ret, done,
    1353             :                                       "smb_iconv failed\n");
    1354             : 
    1355           2 :         blob.length = nconv;
    1356           2 :         torture_assert_data_blob_equal(tctx,
    1357             :                                        src_blob,
    1358             :                                        blob,
    1359             :                                        "Conversion failed\n");
    1360             : 
    1361           0 : done:
    1362           0 :         return ret;
    1363             : }
    1364             : 
    1365           2 : static bool test_utf8_nfc_to_nfd(struct torture_context *tctx)
    1366             : {
    1367             :         smb_iconv_t ic;
    1368             :         DATA_BLOB utf8_nfc_blob;
    1369             :         DATA_BLOB utf8_nfd_blob;
    1370             :         DATA_BLOB blob;
    1371             :         size_t nconv;
    1372           2 :         const char *src = NULL;
    1373           2 :         char *dst = NULL;
    1374             :         size_t dst_left;
    1375             :         size_t srclen;
    1376           2 :         bool ret = true;
    1377             : 
    1378           2 :         ic = smb_iconv_open("UTF8-NFD", "UTF8-NFC");
    1379           2 :         torture_assert_goto(tctx, ic != (smb_iconv_t)-1, ret, done,
    1380             :                             "creating iconv handle\n");
    1381             : 
    1382           2 :         utf8_nfc_blob = base64_decode_data_blob_talloc(tctx, utf8_nfc_base64);
    1383           2 :         torture_assert_not_null_goto(tctx, utf8_nfc_blob.data, ret, done,
    1384             :                                      "OOM\n");
    1385             : 
    1386           2 :         utf8_nfd_blob = base64_decode_data_blob_talloc(tctx, utf8_nfd_base64);
    1387           2 :         torture_assert_not_null_goto(tctx, utf8_nfd_blob.data, ret, done,
    1388             :                                      "OOM\n");
    1389             : 
    1390           2 :         blob = data_blob_talloc_zero(tctx, 255);
    1391           2 :         torture_assert_not_null_goto(tctx, blob.data, ret, done, "OOM\n");
    1392             : 
    1393           2 :         dst = (char *)blob.data;
    1394           2 :         dst_left = blob.length;
    1395           2 :         src = (const char *)utf8_nfc_blob.data;
    1396           2 :         srclen = strlen(src);
    1397             : 
    1398           2 :         nconv = smb_iconv(ic,
    1399             :                           &src,
    1400             :                           &srclen,
    1401             :                           &dst,
    1402             :                           &dst_left);
    1403           2 :         torture_assert_goto(tctx, nconv != (size_t)-1, ret, done,
    1404             :                             "smb_iconv failed\n");
    1405             : 
    1406           2 :         blob.length = nconv + 1; /* +1 for the trailing zero */
    1407           2 :         torture_assert_data_blob_equal(tctx,
    1408             :                                        blob,
    1409             :                                        utf8_nfd_blob,
    1410             :                                        "Conversion failed\n");
    1411             : 
    1412           0 : done:
    1413           0 :         return ret;
    1414             : }
    1415             : 
    1416           2 : static bool test_utf8_nfd_to_nfc(struct torture_context *tctx)
    1417             : {
    1418             :         smb_iconv_t ic;
    1419             :         DATA_BLOB utf8_nfc_blob;
    1420             :         DATA_BLOB utf8_nfd_blob;
    1421             :         DATA_BLOB blob;
    1422             :         size_t nconv;
    1423           2 :         const char *src = NULL;
    1424           2 :         char *dst = NULL;
    1425             :         size_t dst_left;
    1426             :         size_t srclen;
    1427           2 :         bool ret = true;
    1428             : 
    1429           2 :         ic = smb_iconv_open("UTF8-NFC", "UTF8-NFD");
    1430           2 :         torture_assert_goto(tctx, ic != (smb_iconv_t)-1, ret, done,
    1431             :                             "creating iconv handle\n");
    1432             : 
    1433           2 :         utf8_nfc_blob = base64_decode_data_blob_talloc(tctx, utf8_nfc_base64);
    1434           2 :         torture_assert_not_null_goto(tctx, utf8_nfc_blob.data, ret, done,
    1435             :                                      "OOM\n");
    1436             : 
    1437           2 :         utf8_nfd_blob = base64_decode_data_blob_talloc(tctx, utf8_nfd_base64);
    1438           2 :         torture_assert_not_null_goto(tctx, utf8_nfd_blob.data, ret, done,
    1439             :                                      "OOM\n");
    1440             : 
    1441           2 :         blob = data_blob_talloc_zero(tctx, 255);
    1442           2 :         torture_assert_not_null_goto(tctx, blob.data, ret, done, "OOM\n");
    1443             : 
    1444           2 :         dst = (char *)blob.data;
    1445           2 :         dst_left = blob.length;
    1446           2 :         src = (const char *)utf8_nfd_blob.data;
    1447           2 :         srclen = strlen(src);
    1448             : 
    1449           2 :         nconv = smb_iconv(ic,
    1450             :                           &src,
    1451             :                           &srclen,
    1452             :                           &dst,
    1453             :                           &dst_left);
    1454           2 :         torture_assert_goto(tctx, nconv != (size_t)-1, ret, done,
    1455             :                             "smb_iconv failed\n");
    1456             : 
    1457           2 :         blob.length = nconv + 1; /* +1 for the trailing zero */
    1458           2 :         torture_assert_data_blob_equal(tctx,
    1459             :                                        blob,
    1460             :                                        utf8_nfc_blob,
    1461             :                                        "Conversion failed\n");
    1462             : 
    1463           0 : done:
    1464           0 :         return ret;
    1465             : }
    1466             : 
    1467           2 : static bool test_gd_case_utf8_handle(struct torture_context *tctx)
    1468             : {
    1469             :         struct smb_iconv_handle *iconv_handle;
    1470           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
    1471           2 :         DATA_BLOB gd_utf8_upper = base64_decode_data_blob(gd_utf8_upper_base64);
    1472           2 :         DATA_BLOB gd_utf8_lower = base64_decode_data_blob(gd_utf8_lower_base64);
    1473             :         char *gd_lower, *gd_upper;
    1474           2 :         talloc_steal(tctx, gd_utf8.data);
    1475             : 
    1476           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8",
    1477           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
    1478           2 :         torture_assert(tctx, iconv_handle, "getting utf8 iconv handle");
    1479             : 
    1480           2 :         torture_assert(tctx,
    1481             :                        strhasupper_handle(iconv_handle, (const char *)gd_utf8.data),
    1482             :                        "GD's name has an upper case character");
    1483           2 :         torture_assert(tctx,
    1484             :                        strhaslower_handle(iconv_handle, (const char *)gd_utf8.data),
    1485             :                        "GD's name has an lower case character");
    1486           2 :         gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_utf8.data);
    1487           2 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
    1488           2 :         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_lower), gd_utf8_lower,
    1489             :                                        "convert GD's name into lower case");
    1490           2 :         gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_utf8.data, gd_utf8.length);
    1491           0 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
    1492           2 :         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_upper), gd_utf8_upper,
    1493             :                                        "convert GD's name into upper case");
    1494             : 
    1495           2 :         torture_assert(tctx,
    1496             :                        strhasupper_handle(iconv_handle, gd_upper),
    1497             :                        "upper case name has an upper case character");
    1498           2 :         torture_assert(tctx,
    1499             :                        strhaslower_handle(iconv_handle, gd_lower),
    1500             :                        "lower case name has an lower case character");
    1501           2 :         torture_assert(tctx,
    1502             :                        strhasupper_handle(iconv_handle, gd_lower) == false,
    1503             :                        "lower case name has no upper case character");
    1504           2 :         torture_assert(tctx,
    1505             :                        strhaslower_handle(iconv_handle, gd_upper) == false,
    1506             :                        "upper case name has no lower case character");
    1507             : 
    1508           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
    1509             :                                                  gd_upper) == 0,
    1510             :                        "case insensitive comparison orig/upper");
    1511           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
    1512             :                                                  gd_lower) == 0,
    1513             :                        "case insensitive comparison orig/lower");
    1514           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper,
    1515             :                                                  gd_lower) == 0,
    1516             :                        "case insensitive comparison upper/lower");
    1517             : 
    1518             :         /* This string isn't different in length upper/lower */
    1519           2 :         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
    1520             :                                                   gd_upper, gd_utf8.length) == 0,
    1521             :                        "case insensitive comparison orig/upper");
    1522           2 :         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
    1523             :                                                  gd_lower, gd_utf8.length) == 0,
    1524             :                        "case insensitive comparison orig/lower");
    1525           2 :         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper,
    1526             :                                                  gd_lower, gd_utf8.length) == 0,
    1527             :                        "case insensitive comparison upper/lower");
    1528             : 
    1529           2 :         data_blob_free(&gd_utf8);
    1530           2 :         data_blob_free(&gd_utf8_upper);
    1531           2 :         data_blob_free(&gd_utf8_lower);
    1532             : 
    1533           2 :         return true;
    1534             : }
    1535             : 
    1536           2 : static bool test_gd_case_cp850_handle(struct torture_context *tctx)
    1537             : {
    1538             :         struct smb_iconv_handle *iconv_handle;
    1539           2 :         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
    1540           2 :         DATA_BLOB gd_cp850_upper = base64_decode_data_blob(gd_cp850_upper_base64);
    1541           2 :         DATA_BLOB gd_cp850_lower = base64_decode_data_blob(gd_cp850_lower_base64);
    1542             :         char *gd_lower, *gd_upper;
    1543           2 :         talloc_steal(tctx, gd_cp850.data);
    1544             : 
    1545           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "CP850",
    1546           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
    1547           2 :         torture_assert(tctx, iconv_handle, "getting cp850 iconv handle");
    1548             : 
    1549           2 :         torture_assert(tctx,
    1550             :                        strhasupper_handle(iconv_handle, (const char *)gd_cp850.data),
    1551             :                        "GD's name has an upper case character");
    1552           2 :         torture_assert(tctx,
    1553             :                        strhaslower_handle(iconv_handle, (const char *)gd_cp850.data),
    1554             :                        "GD's name has an lower case character");
    1555           2 :         gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_cp850.data);
    1556           2 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
    1557           2 :         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_lower), gd_cp850_lower,
    1558             :                                        "convert GD's name into lower case");
    1559           2 :         gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_cp850.data, gd_cp850.length);
    1560           0 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
    1561           2 :         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_upper), gd_cp850_upper,
    1562             :                                        "convert GD's name into upper case");
    1563             : 
    1564           2 :         torture_assert(tctx,
    1565             :                        strhasupper_handle(iconv_handle, gd_upper),
    1566             :                        "upper case name has an upper case character");
    1567           2 :         torture_assert(tctx,
    1568             :                        strhaslower_handle(iconv_handle, gd_lower),
    1569             :                        "lower case name has an lower case character");
    1570           2 :         torture_assert(tctx,
    1571             :                        strhasupper_handle(iconv_handle, gd_lower) == false,
    1572             :                        "lower case name has no upper case character");
    1573           2 :         torture_assert(tctx,
    1574             :                        strhaslower_handle(iconv_handle, gd_upper) == false,
    1575             :                        "upper case name has no lower case character");
    1576             : 
    1577           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
    1578             :                                                  gd_upper) == 0,
    1579             :                        "case insensitive comparison orig/upper");
    1580           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
    1581             :                                                  gd_lower) == 0,
    1582             :                        "case insensitive comparison orig/lower");
    1583           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper,
    1584             :                                                  gd_lower) == 0,
    1585             :                        "case insensitive comparison upper/lower");
    1586             : 
    1587             :         /* This string isn't different in length upper/lower */
    1588           2 :         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
    1589             :                                                  gd_upper, gd_cp850.length) == 0,
    1590             :                        "case insensitive comparison orig/upper");
    1591           2 :         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
    1592             :                                                  gd_lower, gd_cp850.length) == 0,
    1593             :                        "case insensitive comparison orig/lower");
    1594           2 :         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper,
    1595             :                                                  gd_lower, gd_cp850.length) == 0,
    1596             :                        "case insensitive comparison upper/lower");
    1597             : 
    1598           2 :         data_blob_free(&gd_cp850);
    1599           2 :         data_blob_free(&gd_cp850_upper);
    1600           2 :         data_blob_free(&gd_cp850_lower);
    1601             : 
    1602           2 :         return true;
    1603             : }
    1604             : 
    1605           2 : static bool test_plato_case_utf8_handle(struct torture_context *tctx)
    1606             : {
    1607             :         struct smb_iconv_handle *iconv_handle;
    1608           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
    1609             :         char *plato_lower, *plato_upper;
    1610           2 :         talloc_steal(tctx, plato_utf8.data);
    1611             : 
    1612           2 :         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8",
    1613           2 :                                                 lpcfg_parm_bool(tctx->lp_ctx, NULL, "iconv", "use_builtin_handlers", true));
    1614           2 :         torture_assert(tctx, iconv_handle, "getting utf8 iconv handle");
    1615             : 
    1616           2 :         torture_assert(tctx,
    1617             :                        strhasupper_handle(iconv_handle, (const char *)plato_utf8.data),
    1618             :                        "PLATO's apology has an upper case character");
    1619           2 :         torture_assert(tctx,
    1620             :                        strhaslower_handle(iconv_handle, (const char *)plato_utf8.data),
    1621             :                        "PLATO's apology has an lower case character");
    1622           2 :         plato_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)plato_utf8.data);
    1623           2 :         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case");
    1624           2 :         plato_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)plato_utf8.data, plato_utf8.length);
    1625           0 :         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case");
    1626             : 
    1627           2 :         torture_assert(tctx,
    1628             :                        strhasupper_handle(iconv_handle, plato_upper),
    1629             :                        "upper case string has an upper case character");
    1630           2 :         torture_assert(tctx,
    1631             :                        strhaslower_handle(iconv_handle, plato_lower),
    1632             :                        "lower case string has an lower case character");
    1633           2 :         torture_assert(tctx,
    1634             :                        strhasupper_handle(iconv_handle, plato_lower) == false,
    1635             :                        "lower case string has no upper case character");
    1636           2 :         torture_assert(tctx,
    1637             :                        strhaslower_handle(iconv_handle, plato_upper) == false,
    1638             :                        "upper case string has no lower case character");
    1639             : 
    1640           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data,
    1641             :                                                  plato_upper) == 0,
    1642             :                        "case insensitive comparison orig/upper");
    1643           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data,
    1644             :                                                  plato_lower) == 0,
    1645             :                        "case insensitive comparison orig/lower");
    1646           2 :         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, plato_upper,
    1647             :                                                  plato_lower) == 0,
    1648             :                        "case insensitive comparison upper/lower");
    1649           0 :         return true;
    1650             : }
    1651             : 
    1652           2 : static bool test_gd(struct torture_context *tctx)
    1653             : {
    1654           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
    1655           2 :         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
    1656           2 :         DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64);
    1657           2 :         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
    1658             :         DATA_BLOB gd_output;
    1659             :         size_t saved_len;
    1660             : 
    1661           2 :         talloc_steal(tctx, gd_utf8.data);
    1662           2 :         talloc_steal(tctx, gd_cp850.data);
    1663           2 :         talloc_steal(tctx, gd_iso8859_1.data);
    1664           2 :         talloc_steal(tctx, gd_utf16le.data);
    1665             : 
    1666           2 :         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UTF8,
    1667             :                                                    gd_utf8.data, gd_utf8.length,
    1668             :                                                    (void *)&gd_output.data, &gd_output.length),
    1669             :                        "conversion from UTF8 to utf8 charset");
    1670           2 :         saved_len = gd_output.length;
    1671             : 
    1672           2 :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
    1673             :                                                          gd_utf8.data, gd_utf8.length,
    1674             :                                                          (void *)gd_output.data, gd_output.length,
    1675             :                                                          &gd_output.length),
    1676             :                        "conversion from UTF8 to utf8 charset");
    1677             : 
    1678             :         /* Short output handling confirmation */
    1679           2 :         gd_output.length = 1;
    1680           2 :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
    1681             :                                                          gd_utf8.data, gd_utf8.length,
    1682             :                                                          (void *)gd_output.data, gd_output.length,
    1683             :                                                          &gd_output.length) == false,
    1684             :                        "conversion from UTF8 to any utf8 charset should fail due to too short");
    1685           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to utf8 charset should fail E2BIG");
    1686           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
    1687           2 :         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to utf8 charset incorrect");
    1688             : 
    1689             : #if 0 /* This currently fails as we just copy like-for-like character conversions */
    1690             :         /* Short output handling confirmation */
    1691             :         gd_output.length = 2;
    1692             :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
    1693             :                                                   gd_utf8.data, gd_utf8.length,
    1694             :                                                   (void *)gd_output.data, gd_output.length,
    1695             :                                                   &gd_output.length) == false,
    1696             :                        "conversion from UTF8 to utf8 charset should fail due to too short");
    1697             :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to utf8 charset should fail E2BIG");
    1698             :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
    1699             : 
    1700             :         /* Short input handling confirmation */
    1701             :         gd_output.length = saved_len;
    1702             :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
    1703             :                                                   gd_utf8.data, 2,
    1704             :                                                   (void *)gd_output.data, gd_output.length,
    1705             :                                                   &gd_output.length) == false,
    1706             :                        "conversion from UTF8 to UTF8 should fail due to too short");
    1707             :         torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to UTF8 should fail EINVAL");
    1708             :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
    1709             : #endif
    1710             : 
    1711             :         /* Short output handling confirmation */
    1712           2 :         gd_output.length = 1;
    1713           2 :         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
    1714             :                                                   gd_utf16le.data, gd_utf16le.length,
    1715             :                                                   (void *)gd_output.data, gd_output.length,
    1716             :                                                   &gd_output.length) == false,
    1717             :                        "conversion from UTF16 to UTF8 should fail due to too short");
    1718           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to UTF8 should fail E2BIG");
    1719           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
    1720           2 :         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF16 to UTF8 incorrect");
    1721             : 
    1722             :         /* Short output handling confirmation */
    1723           2 :         gd_output.length = 3;
    1724           2 :         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
    1725             :                                                   gd_utf16le.data, gd_utf16le.length,
    1726             :                                                   (void *)gd_output.data, gd_output.length,
    1727             :                                                   &gd_output.length) == false,
    1728             :                        "conversion from UTF16 to UTF8 should fail due to too short");
    1729           2 :         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to UTF8 should fail E2BIG");
    1730           2 :         torture_assert_int_equal(tctx, gd_output.length, 3, "Should get 3 bytes output for UTF8");
    1731             : 
    1732             :         /* Short input handling confirmation */
    1733           2 :         gd_output.length = saved_len;
    1734           2 :         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
    1735             :                                                   gd_utf16le.data, 3,
    1736             :                                                   (void *)gd_output.data, gd_output.length,
    1737             :                                                   &gd_output.length) == false,
    1738             :                        "conversion from UTF16 to UTF8 should fail due to too short");
    1739           2 :         torture_assert_errno_equal(tctx, EINVAL, "conversion from short UTF16 to UTF8 should fail EINVAL");
    1740           2 :         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
    1741             : 
    1742           0 :         return true;
    1743             : }
    1744             : 
    1745           2 : static bool test_plato(struct torture_context *tctx)
    1746             : {
    1747           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
    1748           2 :         DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64);
    1749             :         DATA_BLOB plato_output;
    1750             :         DATA_BLOB plato_output2;
    1751             : 
    1752           2 :         talloc_steal(tctx, plato_utf8.data);
    1753           2 :         talloc_steal(tctx, plato_utf16le.data);
    1754             : 
    1755           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    1756             :                                                    CH_UTF8, CH_UTF16LE,
    1757             :                                                    plato_utf8.data, plato_utf8.length,
    1758             :                                                    (void *)&plato_output.data, &plato_output.length),
    1759             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1760           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
    1761             : 
    1762           2 :         torture_assert_int_equal(tctx,
    1763             :                                  strlen_m_ext((const char *)plato_utf8.data,
    1764             :                                               CH_UTF8, CH_UTF16LE),
    1765             :                                  plato_output.length / 2,
    1766             :                                  "checking strlen_m_ext of conversion of UTF8 to UTF16LE");
    1767             : 
    1768           4 :         memset(plato_output.data, '\0', plato_output.length);
    1769           2 :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF16LE,
    1770             :                                                   plato_utf8.data, plato_utf8.length,
    1771             :                                                   (void *)plato_output.data, plato_output.length,
    1772             :                                                   &plato_output.length),
    1773             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1774           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
    1775             : 
    1776           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    1777             :                                                    CH_UTF16LE, CH_UTF8,
    1778             :                                                    plato_output.data, plato_output.length,
    1779             :                                                    (void *)&plato_output2.data, &plato_output2.length),
    1780             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1781           2 :         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
    1782             : 
    1783           4 :         memset(plato_output2.data, '\0', plato_output2.length);
    1784           2 :         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
    1785             :                                                   plato_output.data, plato_output.length,
    1786             :                                                   (void *)plato_output2.data, plato_output2.length, &plato_output2.length),
    1787             :                        "conversion of UTF8 ancient greek to UTF16 failed");
    1788           2 :         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
    1789             : 
    1790           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    1791             :                                                    CH_UTF8, CH_UTF8,
    1792             :                                                    plato_utf8.data, plato_utf8.length,
    1793             :                                                    (void *)&plato_output.data, &plato_output.length),
    1794             :                        "conversion of UTF8 to UTF8");
    1795           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8,
    1796             :                                        "conversion of UTF8 to UTF8");
    1797           2 :         torture_assert_int_equal(tctx,
    1798             :                                  strlen_m_ext((const char *)plato_utf8.data,
    1799             :                                               CH_UTF8, CH_UTF8),
    1800             :                                  plato_output.length,
    1801             :                                  "checking strlen_m_ext of conversion of UTF8 to UTF8");
    1802           4 :         memset(plato_output.data, '\0', plato_output.length);
    1803           2 :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
    1804             :                                                   plato_utf8.data, plato_utf8.length,
    1805             :                                                   (void *)plato_output.data, plato_output.length,
    1806             :                                                   &plato_output.length),
    1807             :                        "conversion of UTF8 to UTF8");
    1808           2 :         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8,
    1809             :                                        "conversion of UTF8 to UTF8");
    1810             : 
    1811           4 :         memset(plato_output.data, '\0', plato_output.length);
    1812           2 :         torture_assert(tctx, convert_string_error(CH_UTF8, CH_DOS,
    1813             :                                                   plato_utf8.data, plato_utf8.length,
    1814             :                                                   (void *)plato_output.data, plato_output.length,
    1815             :                                                   &plato_output.length) == false,
    1816             :                        "conversion of UTF8 to any dos charset should fail");
    1817           2 :         torture_assert_errno_equal(tctx,  EILSEQ, "conversion of UTF16 ancient greek to any DOS charset should fail EILSEQ");
    1818             : 
    1819           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    1820             :                                                    CH_UTF8, CH_DOS,
    1821             :                                                    plato_utf8.data, plato_utf8.length,
    1822             :                                                    (void *)&plato_output.data, &plato_output.length) == false,
    1823             :                        "conversion of UTF8 ancient greek to any DOS charset should fail");
    1824             : 
    1825             :         /* Allocate only enough space for a partial conversion */
    1826           2 :         plato_output = data_blob_talloc(tctx, NULL, 9);
    1827           2 :         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
    1828             :                                                   plato_utf16le.data, plato_utf16le.length,
    1829             :                                                   (void *)plato_output.data, plato_output.length,
    1830             :                                                   &plato_output.length) == false,
    1831             :                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1832           2 :         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1833           2 :         torture_assert_int_equal(tctx, plato_output.length, 8,
    1834             :                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
    1835             : 
    1836           2 :         plato_output = data_blob_talloc(tctx, NULL, 2);
    1837           2 :         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
    1838             :                                                   plato_utf16le.data, plato_utf16le.length,
    1839             :                                                   (void *)plato_output.data, plato_output.length,
    1840             :                                                   &plato_output.length) == false,
    1841             :                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1842           2 :         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
    1843           2 :         torture_assert_int_equal(tctx, plato_output.length, 0,
    1844             :                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
    1845             : 
    1846             : 
    1847           0 :         return true;
    1848             : }
    1849             : 
    1850           2 : static bool test_plato_latin(struct torture_context *tctx)
    1851             : {
    1852           2 :         DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64);
    1853           2 :         DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64);
    1854             :         DATA_BLOB plato_latin_output;
    1855             : 
    1856           2 :         talloc_steal(tctx, plato_latin_utf8.data);
    1857           2 :         talloc_steal(tctx, plato_latin_utf16le.data);
    1858             : 
    1859           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    1860             :                                                     CH_UTF16LE, CH_UTF8,
    1861             :                                                     plato_latin_utf16le.data, plato_latin_utf16le.length,
    1862             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
    1863             :                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
    1864           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16 to UTF8 incorrect");
    1865             : 
    1866           2 :         torture_assert_int_equal(tctx,
    1867             :                                  strlen_m_ext((const char *)plato_latin_output.data,
    1868             :                                               CH_UTF8, CH_UTF16LE),
    1869             :                                  plato_latin_utf16le.length / 2,
    1870             :                                  "checking strlen_m_ext UTF16 latin charset greek to UTF8");
    1871           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    1872             :                                                     CH_UTF8, CH_UTF16LE,
    1873             :                                                     plato_latin_utf8.data, plato_latin_utf8.length,
    1874             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
    1875             :                        "conversion of UTF16 latin charset greek to UTF16LE failed");
    1876           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf16le, "conversion from UTF8 to UTF16LE incorrect");
    1877             : 
    1878           0 :         return true;
    1879             : }
    1880             : 
    1881           2 : static bool test_gd_case(struct torture_context *tctx)
    1882             : {
    1883           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
    1884             :         char *gd_unix;
    1885             :         size_t gd_size;
    1886             :         char *gd_lower, *gd_upper;
    1887           2 :         talloc_steal(tctx, gd_utf8.data);
    1888             : 
    1889           2 :         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX,
    1890             :                                                    gd_utf8.data, gd_utf8.length,
    1891             :                                                    (void *)&gd_unix, &gd_size),
    1892             :                        "conversion of unix charset to UTF8");
    1893             : 
    1894           2 :         gd_lower = strlower_talloc(tctx, gd_unix);
    1895           2 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
    1896           2 :         gd_upper = strupper_talloc_n(tctx, gd_unix, gd_size);
    1897           0 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
    1898             : 
    1899           2 :         torture_assert(tctx,
    1900             :                        strhasupper(gd_unix),
    1901             :                        "GD's name has an upper case character");
    1902           2 :         torture_assert(tctx,
    1903             :                        strhaslower(gd_unix),
    1904             :                        "GD's name has an lower case character");
    1905           2 :         torture_assert(tctx,
    1906             :                        strhasupper(gd_upper),
    1907             :                        "upper case name has an upper case character");
    1908           2 :         torture_assert(tctx,
    1909             :                        strhaslower(gd_lower),
    1910             :                        "lower case name has an lower case character");
    1911           2 :         torture_assert(tctx,
    1912             :                        strhasupper(gd_lower) == false,
    1913             :                        "lower case name has no upper case character");
    1914           2 :         torture_assert(tctx,
    1915             :                        strhaslower(gd_upper) == false,
    1916             :                        "upper case name has no lower case character");
    1917             : 
    1918           2 :         torture_assert(tctx, strcasecmp_m(gd_unix,
    1919             :                                                  gd_upper) == 0,
    1920             :                        "case insensitive comparison orig/upper");
    1921           2 :         torture_assert(tctx, strcasecmp_m(gd_unix,
    1922             :                                                  gd_lower) == 0,
    1923             :                        "case insensitive comparison orig/lower");
    1924           2 :         torture_assert(tctx, strcasecmp_m(gd_upper,
    1925             :                                                  gd_lower) == 0,
    1926             :                        "case insensitive comparison upper/lower");
    1927             : 
    1928             :         /* This string isn't different in length upper/lower, but just check the first 5 chars */
    1929           2 :         torture_assert(tctx, strncasecmp_m(gd_unix,
    1930             :                                                   gd_upper, 5) == 0,
    1931             :                        "case insensitive comparison orig/upper");
    1932           2 :         torture_assert(tctx, strncasecmp_m(gd_unix,
    1933             :                                                  gd_lower, 5) == 0,
    1934             :                        "case insensitive comparison orig/lower");
    1935           2 :         torture_assert(tctx, strncasecmp_m(gd_upper,
    1936             :                                                  gd_lower, 5) == 0,
    1937             :                        "case insensitive comparison upper/lower");
    1938           0 :         return true;
    1939             : }
    1940             : 
    1941           2 : static bool test_plato_case(struct torture_context *tctx)
    1942             : {
    1943           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
    1944             :         char *plato_unix;
    1945             :         size_t plato_length;
    1946             :         char *plato_lower, *plato_upper;
    1947           2 :         talloc_steal(tctx, plato_utf8.data);
    1948             : 
    1949           2 :         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX,
    1950             :                                                    plato_utf8.data, plato_utf8.length,
    1951             :                                                    (void *)&plato_unix, &plato_length),
    1952             :                        "conversion of unix charset to UTF8");
    1953             : 
    1954           2 :         torture_assert(tctx,
    1955             :                        strhasupper(plato_unix),
    1956             :                        "PLATO's apology has an upper case character");
    1957           2 :         torture_assert(tctx,
    1958             :                        strhaslower(plato_unix),
    1959             :                        "PLATO's apology has an lower case character");
    1960           2 :         plato_lower = strlower_talloc(tctx, plato_unix);
    1961           2 :         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case");
    1962           2 :         plato_upper = strupper_talloc_n(tctx, plato_unix, plato_utf8.length);
    1963           0 :         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case");
    1964             : 
    1965           2 :         torture_assert(tctx,
    1966             :                        strhasupper(plato_upper),
    1967             :                        "upper case string has an upper case character");
    1968           2 :         torture_assert(tctx,
    1969             :                        strhaslower(plato_lower),
    1970             :                        "lower case string has an lower case character");
    1971           2 :         torture_assert(tctx,
    1972             :                        strhasupper(plato_lower) == false,
    1973             :                        "lower case string has no upper case character");
    1974           2 :         torture_assert(tctx,
    1975             :                        strhaslower(plato_upper) == false,
    1976             :                        "upper case string has no lower case character");
    1977             : 
    1978           2 :         torture_assert(tctx, strcasecmp_m(plato_unix,
    1979             :                                                  plato_upper) == 0,
    1980             :                        "case insensitive comparison orig/upper");
    1981           2 :         torture_assert(tctx, strcasecmp_m(plato_unix,
    1982             :                                                  plato_lower) == 0,
    1983             :                        "case insensitive comparison orig/lower");
    1984           2 :         torture_assert(tctx, strcasecmp_m(plato_upper,
    1985             :                                                  plato_lower) == 0,
    1986             :                        "case insensitive comparison upper/lower");
    1987           0 :         return true;
    1988             : }
    1989             : 
    1990        2353 : struct torture_suite *torture_local_convert_string_handle(TALLOC_CTX *mem_ctx)
    1991             : {
    1992        2353 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string_handle");
    1993        2353 :         torture_suite_add_simple_test(suite, "cp850 high points", test_cp850_high_points);
    1994             : 
    1995        2353 :         torture_suite_add_simple_test(suite, "gd_ascii", test_gd_ascii_handle);
    1996        2353 :         torture_suite_add_simple_test(suite, "gd_minus_1", test_gd_minus_1_handle);
    1997        2353 :         torture_suite_add_simple_test(suite, "gd_iso8859_cp850", test_gd_iso8859_cp850_handle);
    1998        2353 :         torture_suite_add_simple_test(suite, "plato_english_iso8859_cp850", test_plato_english_iso8859_cp850_handle);
    1999        2353 :         torture_suite_add_simple_test(suite, "plato_english_minus_1", test_plato_english_minus_1_handle);
    2000        2353 :         torture_suite_add_simple_test(suite, "plato_cp850_utf8", test_plato_cp850_utf8_handle);
    2001        2353 :         torture_suite_add_simple_test(suite, "plato_minus_1", test_plato_minus_1_handle);
    2002        2353 :         torture_suite_add_simple_test(suite, "plato_latin_cp850_utf8", test_plato_latin_cp850_utf8_handle);
    2003        2353 :         torture_suite_add_simple_test(suite, "utf8-nfc-to-nfd", test_utf8_nfc_to_nfd);
    2004        2353 :         torture_suite_add_simple_test(suite, "utf8-nfc-to-nfd-overflow", test_utf8_nfc_to_nfd_overflow);
    2005        2353 :         torture_suite_add_simple_test(suite, "utf8-nfd-to-nfc", test_utf8_nfd_to_nfc);
    2006        2353 :         return suite;
    2007             : }
    2008             : 
    2009        2353 : struct torture_suite *torture_local_string_case_handle(TALLOC_CTX *mem_ctx)
    2010             : {
    2011        2353 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle");
    2012             : 
    2013        2353 :         torture_suite_add_simple_test(suite, "gd_case_utf8", test_gd_case_utf8_handle);
    2014        2353 :         torture_suite_add_simple_test(suite, "gd_case_cp850", test_gd_case_cp850_handle);
    2015        2353 :         torture_suite_add_simple_test(suite, "plato_case_utf8", test_plato_case_utf8_handle);
    2016        2353 :         return suite;
    2017             : }
    2018             : 
    2019        2353 : struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx)
    2020             : {
    2021        2353 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string");
    2022             : 
    2023        2353 :         torture_suite_add_simple_test(suite, "gd", test_gd);
    2024        2353 :         torture_suite_add_simple_test(suite, "plato", test_plato);
    2025        2353 :         torture_suite_add_simple_test(suite, "plato_latin", test_plato_latin);
    2026        2353 :         return suite;
    2027             : }
    2028             : 
    2029        2353 : struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx)
    2030             : {
    2031        2353 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle");
    2032             : 
    2033        2353 :         torture_suite_add_simple_test(suite, "gd_case", test_gd_case);
    2034        2353 :         torture_suite_add_simple_test(suite, "plato_case", test_plato_case);
    2035        2353 :         return suite;
    2036             : }

Generated by: LCOV version 1.13