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 2f515e9b Lines: 861 883 97.5 %
Date: 2024-04-21 15:09:00 Functions: 25 25 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           2 :         DATA_BLOB utf8;
     116           2 :         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           2 :         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           2 :         DATA_BLOB gd_output;
     163           2 :         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           2 :         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           2 :         DATA_BLOB gd_output;
     355           2 :         DATA_BLOB gd_utf8_terminated;
     356           2 :         DATA_BLOB gd_cp850_terminated;
     357           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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 illegal sequence");
     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           2 :         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           2 :         DATA_BLOB plato_english_output;
     614           2 :         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           2 :         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           2 :         DATA_BLOB plato_english_output;
     732           2 :         DATA_BLOB plato_english_utf8_terminated;
     733           2 :         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           2 :         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           2 :         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           2 :         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           2 :         DATA_BLOB plato_output;
     873           2 :         DATA_BLOB plato_utf8_terminated;
     874           2 :         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           2 :         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           2 :         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           2 :         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           2 :         DATA_BLOB plato_output;
     989           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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           2 :         DATA_BLOB plato_latin_output;
    1181           2 :         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           2 :         smb_iconv_t ic;
    1249           2 :         DATA_BLOB utf8_nfc_blob;
    1250           2 :         DATA_BLOB utf8_nfd_blob;
    1251           2 :         DATA_BLOB src_blob;
    1252           2 :         DATA_BLOB blob;
    1253           2 :         size_t nconv;
    1254           2 :         const char *src = NULL;
    1255           2 :         char *dst = NULL;
    1256           2 :         size_t dst_left;
    1257           2 :         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           2 :         smb_iconv_t ic;
    1368           2 :         DATA_BLOB utf8_nfc_blob;
    1369           2 :         DATA_BLOB utf8_nfd_blob;
    1370           2 :         DATA_BLOB blob;
    1371           2 :         size_t nconv;
    1372           2 :         const char *src = NULL;
    1373           2 :         char *dst = NULL;
    1374           2 :         size_t dst_left;
    1375           2 :         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           2 :         smb_iconv_t ic;
    1419           2 :         DATA_BLOB utf8_nfc_blob;
    1420           2 :         DATA_BLOB utf8_nfd_blob;
    1421           2 :         DATA_BLOB blob;
    1422           2 :         size_t nconv;
    1423           2 :         const char *src = NULL;
    1424           2 :         char *dst = NULL;
    1425           2 :         size_t dst_left;
    1426           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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           2 :         struct smb_iconv_handle *iconv_handle;
    1608           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
    1609           2 :         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           2 :         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           2 :         DATA_BLOB gd_output;
    1659           2 :         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           2 :         DATA_BLOB plato_output;
    1750           2 :         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           2 :         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           2 :         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           2 :         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           2 :         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             : 
    1851             : 
    1852           2 : static bool test_short_strings(struct torture_context *tctx)
    1853             : {
    1854           2 :         char zeros[6] = {0};
    1855           2 :         char s[6] =     {'s'};
    1856           2 :         bool ok;
    1857           2 :         char *out;
    1858           2 :         size_t out_len;
    1859             : 
    1860           2 :         ok = convert_string_talloc(tctx,
    1861             :                                    CH_UTF8, CH_UTF16LE,
    1862             :                                    zeros, 0,
    1863             :                                    &out, &out_len);
    1864           2 :         torture_assert(tctx, ok, "{\"\", 0} to utf16 failed");
    1865           2 :         torture_assert(tctx, out_len == 2, "{\"\", 0} length is two");
    1866           2 :         torture_assert(tctx, out[0] == 0 && out[1] == 0, "{\"\", 0} utf16 is zero");
    1867           2 :         TALLOC_FREE(out);
    1868             : 
    1869           2 :         ok = convert_string_talloc(tctx,
    1870             :                                    CH_UTF8, CH_UTF16LE,
    1871             :                                    zeros, 1,
    1872             :                                    &out, &out_len);
    1873           2 :         torture_assert(tctx, ok, "{\"\\0\", 1} to utf16 failed");
    1874           2 :         torture_assert(tctx, out_len == 2, "{\"\\0\", 1} length is two");
    1875           2 :         torture_assert(tctx, out[0] == 0 && out[1] == 0, "{\"\\0\", 1} utf16 is zero");
    1876           2 :         TALLOC_FREE(out);
    1877             : 
    1878           2 :         ok = convert_string_talloc(tctx,
    1879             :                                    CH_UTF8, CH_UTF16LE,
    1880             :                                    zeros, 2,
    1881             :                                    &out, &out_len);
    1882           2 :         torture_assert(tctx, ok, "{\"\\0\\0\", 2} to utf16 failed");
    1883           2 :         torture_assert(tctx, out_len == 4, "{\"\\0\\0\", 2} length is four");
    1884           2 :         torture_assert(tctx, out[0] == 0 && out[1] == 0, "{\"\\0\\0\", 2} utf16 is zero");
    1885           2 :         TALLOC_FREE(out);
    1886             : 
    1887           2 :         ok = convert_string_talloc(tctx,
    1888             :                                    CH_UTF8, CH_UTF16LE,
    1889             :                                    s, 0,
    1890             :                                    &out, &out_len);
    1891           2 :         torture_assert(tctx, ok, "{\"s\", 0} to utf16 failed");
    1892           2 :         torture_assert(tctx, out_len == 2, "{\"s\", 0} length is two");
    1893           2 :         torture_assert(tctx, out[0] == 0 && out[1] == 0,
    1894             :                        "{\"s\", 0} utf16 is zero");
    1895           2 :         TALLOC_FREE(out);
    1896             : 
    1897           2 :         ok = convert_string_talloc(tctx,
    1898             :                                    CH_UTF8, CH_UTF16LE,
    1899             :                                    s, 1,
    1900             :                                    &out, &out_len);
    1901           2 :         torture_assert(tctx, ok, "{\"s\", 1} to utf16 failed");
    1902           2 :         torture_assert(tctx, out_len == 2, "{\"s\", 1} length is two");
    1903           2 :         torture_assert(tctx, out[0] == 's' && out[1] == 0,
    1904             :                        "{\"s\", 1} utf16 is s");
    1905           2 :         TALLOC_FREE(out);
    1906             : 
    1907           2 :         ok = convert_string_talloc(tctx,
    1908             :                                    CH_UTF8, CH_UTF16LE,
    1909             :                                    s, 2,
    1910             :                                    &out, &out_len);
    1911           2 :         torture_assert(tctx, ok, "{\"s\\0\", 2} to utf16 failed");
    1912           2 :         torture_assert(tctx, out_len == 4, "{\"s\\0\", 2} length is four");
    1913           2 :         torture_assert(tctx, out[0] == 's' && out[1] == 0,
    1914             :                        "{\"s\\0\", 0} utf16 is s");
    1915           2 :         TALLOC_FREE(out);
    1916             : 
    1917             : 
    1918             :         /* going to utf8 */
    1919           2 :         ok = convert_string_talloc(tctx,
    1920             :                                    CH_UTF16LE, CH_UTF8,
    1921             :                                    zeros, 0,
    1922             :                                    &out, &out_len);
    1923           2 :         torture_assert(tctx, ok, "{\"\", 0} to utf8 failed");
    1924           2 :         torture_assert(tctx, out_len == 1, "{\"\", 0} length is one");
    1925           2 :         torture_assert(tctx, out[0] == 0, "{\"\", 0} utf8[0] is zero");
    1926           2 :         TALLOC_FREE(out);
    1927             : 
    1928           2 :         ok = convert_string_talloc(tctx,
    1929             :                                    CH_UTF16LE, CH_UTF8,
    1930             :                                    zeros, 2,
    1931             :                                    &out, &out_len);
    1932           2 :         torture_assert(tctx, ok, "{\"\\0\", 1} to utf8 failed");
    1933           2 :         torture_assert(tctx, out_len == 1, "{\"\\0\", 1} length is one");
    1934           2 :         torture_assert(tctx, out[0] == 0 && out[1] == 0,
    1935             :                        "{\"\\0\", 1} utf8 is zero");
    1936           2 :         TALLOC_FREE(out);
    1937             : 
    1938           2 :         ok = convert_string_talloc(tctx,
    1939             :                                    CH_UTF16LE, CH_UTF8,
    1940             :                                    zeros, 4,
    1941             :                                    &out, &out_len);
    1942           2 :         torture_assert(tctx, ok, "{\"\\0\\0\\0\\0\", 4} to utf8 failed");
    1943           2 :         torture_assert(tctx, out_len == 2, "{\"\\0\\0\\0\\0\", 4} length is two");
    1944           2 :         torture_assert(tctx, out[0] == 0 && out[1] == 0,
    1945             :                        "{\"\\0\\0\\0\\0\", 4} utf8 is zero");
    1946           2 :         TALLOC_FREE(out);
    1947             : 
    1948           2 :         ok = convert_string_talloc(tctx,
    1949             :                                    CH_UTF16LE, CH_UTF8,
    1950             :                                    s, 0,
    1951             :                                    &out, &out_len);
    1952           2 :         torture_assert(tctx, ok, "{\"s\", 0} to utf8 failed");
    1953           2 :         torture_assert(tctx, out_len == 1, "{\"s\", 0} length is one");
    1954           2 :         torture_assert(tctx, out[0] == 0, "{\"s\", 0} utf8 is zero");
    1955           2 :         TALLOC_FREE(out);
    1956             : 
    1957           2 :         ok = convert_string_talloc(tctx,
    1958             :                                    CH_UTF16LE, CH_UTF8,
    1959             :                                    s, 2,
    1960             :                                    &out, &out_len);
    1961           2 :         torture_assert(tctx, ok, "{\"s\\0\", 2} to utf8 failed");
    1962           2 :         torture_assert(tctx, out_len == 1, "{\"s\\0\", 2} length is one");
    1963           2 :         torture_assert(tctx, out[0] == 's' && out[1] == 0,
    1964             :                        "{\"s\\0\", 2} utf8 is s");
    1965           2 :         TALLOC_FREE(out);
    1966             : 
    1967             : 
    1968           2 :         ok = convert_string_talloc(tctx,
    1969             :                                    CH_UTF16LE, CH_UTF8,
    1970             :                                    s, 4,
    1971             :                                    &out, &out_len);
    1972           2 :         torture_assert(tctx, ok, "{\"s\\0\\0\\0\", 4} utf8 failed");
    1973           2 :         torture_assert(tctx, out_len == 2, "\"s\\0\\0\\0\", 4} utf8 length is two");
    1974           2 :         torture_assert(tctx, out[0] == 's' && out[1] == 0,
    1975             :                        "{\"s\\0\\0\\0\", 4} utf8 is s");
    1976           2 :         TALLOC_FREE(out);
    1977             : 
    1978             :         /* odd numbers of bytes from UTF-16 should fail */
    1979           2 :         ok = convert_string_talloc(tctx,
    1980             :                                    CH_UTF16LE, CH_UTF8,
    1981             :                                    s, 1,
    1982             :                                    &out, &out_len);
    1983           2 :         torture_assert(tctx, ! ok, "{\"s\", 1} to utf8 should have failed");
    1984             : 
    1985           2 :         ok = convert_string_talloc(tctx,
    1986             :                                    CH_UTF16LE, CH_UTF8,
    1987             :                                    s, 3,
    1988             :                                    &out, &out_len);
    1989           2 :         torture_assert(tctx, ! ok, "{\"s\\0\\0\", 3} to utf8 should have failed");
    1990             : 
    1991           2 :         ok = convert_string_talloc(tctx,
    1992             :                                    CH_UTF16LE, CH_UTF8,
    1993             :                                    zeros, 1,
    1994             :                                    &out, &out_len);
    1995           2 :         torture_assert(tctx, ! ok,
    1996             :                        "{\"\\0\", 1} to utf8 should have failed");
    1997             : 
    1998           2 :         ok = convert_string_talloc(tctx,
    1999             :                                    CH_UTF16LE, CH_UTF8,
    2000             :                                    zeros, 5,
    2001             :                                    &out, &out_len);
    2002           2 :         torture_assert(tctx, ! ok,
    2003             :                        "{\"\\0\\0\\0\\0\", 5} to utf8 should have failed");
    2004             : 
    2005           0 :         return true;
    2006             : }
    2007             : 
    2008             : 
    2009           2 : static bool test_plato_latin(struct torture_context *tctx)
    2010             : {
    2011           2 :         DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64);
    2012           2 :         DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64);
    2013           2 :         DATA_BLOB plato_latin_output;
    2014             : 
    2015           2 :         talloc_steal(tctx, plato_latin_utf8.data);
    2016           2 :         talloc_steal(tctx, plato_latin_utf16le.data);
    2017             : 
    2018           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    2019             :                                                     CH_UTF16LE, CH_UTF8,
    2020             :                                                     plato_latin_utf16le.data, plato_latin_utf16le.length,
    2021             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
    2022             :                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
    2023           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16 to UTF8 incorrect");
    2024             : 
    2025           2 :         torture_assert_int_equal(tctx,
    2026             :                                  strlen_m_ext((const char *)plato_latin_output.data,
    2027             :                                               CH_UTF8, CH_UTF16LE),
    2028             :                                  plato_latin_utf16le.length / 2,
    2029             :                                  "checking strlen_m_ext UTF16 latin charset greek to UTF8");
    2030           2 :         torture_assert(tctx, convert_string_talloc(tctx,
    2031             :                                                     CH_UTF8, CH_UTF16LE,
    2032             :                                                     plato_latin_utf8.data, plato_latin_utf8.length,
    2033             :                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
    2034             :                        "conversion of UTF16 latin charset greek to UTF16LE failed");
    2035           2 :         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf16le, "conversion from UTF8 to UTF16LE incorrect");
    2036             : 
    2037           0 :         return true;
    2038             : }
    2039             : 
    2040           2 : static bool test_gd_case(struct torture_context *tctx)
    2041             : {
    2042           2 :         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
    2043           2 :         char *gd_unix;
    2044           2 :         size_t gd_size;
    2045           2 :         char *gd_lower, *gd_upper;
    2046           2 :         talloc_steal(tctx, gd_utf8.data);
    2047             : 
    2048           2 :         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX,
    2049             :                                                    gd_utf8.data, gd_utf8.length,
    2050             :                                                    (void *)&gd_unix, &gd_size),
    2051             :                        "conversion of unix charset to UTF8");
    2052             : 
    2053           2 :         gd_lower = strlower_talloc(tctx, gd_unix);
    2054           2 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
    2055           2 :         gd_upper = strupper_talloc_n(tctx, gd_unix, gd_size);
    2056           2 :         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
    2057             : 
    2058           2 :         torture_assert(tctx,
    2059             :                        strhasupper(gd_unix),
    2060             :                        "GD's name has an upper case character");
    2061           2 :         torture_assert(tctx,
    2062             :                        strhaslower(gd_unix),
    2063             :                        "GD's name has an lower case character");
    2064           2 :         torture_assert(tctx,
    2065             :                        strhasupper(gd_upper),
    2066             :                        "upper case name has an upper case character");
    2067           2 :         torture_assert(tctx,
    2068             :                        strhaslower(gd_lower),
    2069             :                        "lower case name has an lower case character");
    2070           2 :         torture_assert(tctx,
    2071             :                        strhasupper(gd_lower) == false,
    2072             :                        "lower case name has no upper case character");
    2073           2 :         torture_assert(tctx,
    2074             :                        strhaslower(gd_upper) == false,
    2075             :                        "upper case name has no lower case character");
    2076             : 
    2077           2 :         torture_assert(tctx, strcasecmp_m(gd_unix,
    2078             :                                                  gd_upper) == 0,
    2079             :                        "case insensitive comparison orig/upper");
    2080           2 :         torture_assert(tctx, strcasecmp_m(gd_unix,
    2081             :                                                  gd_lower) == 0,
    2082             :                        "case insensitive comparison orig/lower");
    2083           2 :         torture_assert(tctx, strcasecmp_m(gd_upper,
    2084             :                                                  gd_lower) == 0,
    2085             :                        "case insensitive comparison upper/lower");
    2086             : 
    2087             :         /* This string isn't different in length upper/lower, but just check the first 5 chars */
    2088           2 :         torture_assert(tctx, strncasecmp_m(gd_unix,
    2089             :                                                   gd_upper, 5) == 0,
    2090             :                        "case insensitive comparison orig/upper");
    2091           2 :         torture_assert(tctx, strncasecmp_m(gd_unix,
    2092             :                                                  gd_lower, 5) == 0,
    2093             :                        "case insensitive comparison orig/lower");
    2094           2 :         torture_assert(tctx, strncasecmp_m(gd_upper,
    2095             :                                                  gd_lower, 5) == 0,
    2096             :                        "case insensitive comparison upper/lower");
    2097           0 :         return true;
    2098             : }
    2099             : 
    2100           2 : static bool test_plato_case(struct torture_context *tctx)
    2101             : {
    2102           2 :         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
    2103           2 :         char *plato_unix;
    2104           2 :         size_t plato_length;
    2105           2 :         char *plato_lower, *plato_upper;
    2106           2 :         talloc_steal(tctx, plato_utf8.data);
    2107             : 
    2108           2 :         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX,
    2109             :                                                    plato_utf8.data, plato_utf8.length,
    2110             :                                                    (void *)&plato_unix, &plato_length),
    2111             :                        "conversion of unix charset to UTF8");
    2112             : 
    2113           2 :         torture_assert(tctx,
    2114             :                        strhasupper(plato_unix),
    2115             :                        "PLATO's apology has an upper case character");
    2116           2 :         torture_assert(tctx,
    2117             :                        strhaslower(plato_unix),
    2118             :                        "PLATO's apology has an lower case character");
    2119           2 :         plato_lower = strlower_talloc(tctx, plato_unix);
    2120           2 :         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case");
    2121           2 :         plato_upper = strupper_talloc_n(tctx, plato_unix, plato_utf8.length);
    2122           2 :         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case");
    2123             : 
    2124           2 :         torture_assert(tctx,
    2125             :                        strhasupper(plato_upper),
    2126             :                        "upper case string has an upper case character");
    2127           2 :         torture_assert(tctx,
    2128             :                        strhaslower(plato_lower),
    2129             :                        "lower case string has an lower case character");
    2130           2 :         torture_assert(tctx,
    2131             :                        strhasupper(plato_lower) == false,
    2132             :                        "lower case string has no upper case character");
    2133           2 :         torture_assert(tctx,
    2134             :                        strhaslower(plato_upper) == false,
    2135             :                        "upper case string has no lower case character");
    2136             : 
    2137           2 :         torture_assert(tctx, strcasecmp_m(plato_unix,
    2138             :                                                  plato_upper) == 0,
    2139             :                        "case insensitive comparison orig/upper");
    2140           2 :         torture_assert(tctx, strcasecmp_m(plato_unix,
    2141             :                                                  plato_lower) == 0,
    2142             :                        "case insensitive comparison orig/lower");
    2143           2 :         torture_assert(tctx, strcasecmp_m(plato_upper,
    2144             :                                                  plato_lower) == 0,
    2145             :                        "case insensitive comparison upper/lower");
    2146           0 :         return true;
    2147             : }
    2148             : 
    2149        2354 : struct torture_suite *torture_local_convert_string_handle(TALLOC_CTX *mem_ctx)
    2150             : {
    2151        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string_handle");
    2152        2354 :         torture_suite_add_simple_test(suite, "cp850 high points", test_cp850_high_points);
    2153             : 
    2154        2354 :         torture_suite_add_simple_test(suite, "gd_ascii", test_gd_ascii_handle);
    2155        2354 :         torture_suite_add_simple_test(suite, "gd_minus_1", test_gd_minus_1_handle);
    2156        2354 :         torture_suite_add_simple_test(suite, "gd_iso8859_cp850", test_gd_iso8859_cp850_handle);
    2157        2354 :         torture_suite_add_simple_test(suite, "plato_english_iso8859_cp850", test_plato_english_iso8859_cp850_handle);
    2158        2354 :         torture_suite_add_simple_test(suite, "plato_english_minus_1", test_plato_english_minus_1_handle);
    2159        2354 :         torture_suite_add_simple_test(suite, "plato_cp850_utf8", test_plato_cp850_utf8_handle);
    2160        2354 :         torture_suite_add_simple_test(suite, "plato_minus_1", test_plato_minus_1_handle);
    2161        2354 :         torture_suite_add_simple_test(suite, "plato_latin_cp850_utf8", test_plato_latin_cp850_utf8_handle);
    2162        2354 :         torture_suite_add_simple_test(suite, "utf8-nfc-to-nfd", test_utf8_nfc_to_nfd);
    2163        2354 :         torture_suite_add_simple_test(suite, "utf8-nfc-to-nfd-overflow", test_utf8_nfc_to_nfd_overflow);
    2164        2354 :         torture_suite_add_simple_test(suite, "utf8-nfd-to-nfc", test_utf8_nfd_to_nfc);
    2165        2354 :         return suite;
    2166             : }
    2167             : 
    2168        2354 : struct torture_suite *torture_local_string_case_handle(TALLOC_CTX *mem_ctx)
    2169             : {
    2170        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle");
    2171             : 
    2172        2354 :         torture_suite_add_simple_test(suite, "gd_case_utf8", test_gd_case_utf8_handle);
    2173        2354 :         torture_suite_add_simple_test(suite, "gd_case_cp850", test_gd_case_cp850_handle);
    2174        2354 :         torture_suite_add_simple_test(suite, "plato_case_utf8", test_plato_case_utf8_handle);
    2175        2354 :         return suite;
    2176             : }
    2177             : 
    2178        2354 : struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx)
    2179             : {
    2180        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string");
    2181             : 
    2182        2354 :         torture_suite_add_simple_test(suite, "short_strings", test_short_strings);
    2183        2354 :         torture_suite_add_simple_test(suite, "gd", test_gd);
    2184        2354 :         torture_suite_add_simple_test(suite, "plato", test_plato);
    2185        2354 :         torture_suite_add_simple_test(suite, "plato_latin", test_plato_latin);
    2186        2354 :         return suite;
    2187             : }
    2188             : 
    2189        2354 : struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx)
    2190             : {
    2191        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle");
    2192             : 
    2193        2354 :         torture_suite_add_simple_test(suite, "gd_case", test_gd_case);
    2194        2354 :         torture_suite_add_simple_test(suite, "plato_case", test_plato_case);
    2195        2354 :         return suite;
    2196             : }

Generated by: LCOV version 1.14