tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ZydisString.c (13838B)


      1 /***************************************************************************************************
      2 
      3  Zyan Disassembler Library (Zydis)
      4 
      5  Original Author : Florian Bernd, Joel Hoener
      6 
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in all
     15 * copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23 * SOFTWARE.
     24 
     25 ***************************************************************************************************/
     26 
     27 #include "zydis/Zydis/Internal/String.h"
     28 
     29 /* ============================================================================================== */
     30 /* Constants                                                                                      */
     31 /* ============================================================================================== */
     32 
     33 /* ---------------------------------------------------------------------------------------------- */
     34 /* Defines                                                                                        */
     35 /* ---------------------------------------------------------------------------------------------- */
     36 
     37 #define ZYDIS_MAXCHARS_DEC_32 10
     38 #define ZYDIS_MAXCHARS_DEC_64 20
     39 #define ZYDIS_MAXCHARS_HEX_32  8
     40 #define ZYDIS_MAXCHARS_HEX_64 16
     41 
     42 /* ---------------------------------------------------------------------------------------------- */
     43 /* Lookup Tables                                                                                  */
     44 /* ---------------------------------------------------------------------------------------------- */
     45 
     46 static const char* const DECIMAL_LOOKUP =
     47    "00010203040506070809"
     48    "10111213141516171819"
     49    "20212223242526272829"
     50    "30313233343536373839"
     51    "40414243444546474849"
     52    "50515253545556575859"
     53    "60616263646566676869"
     54    "70717273747576777879"
     55    "80818283848586878889"
     56    "90919293949596979899";
     57 
     58 /* ---------------------------------------------------------------------------------------------- */
     59 
     60 /* ============================================================================================== */
     61 /* Internal Functions                                                                             */
     62 /* ============================================================================================== */
     63 
     64 /* ---------------------------------------------------------------------------------------------- */
     65 /* Decimal                                                                                        */
     66 /* ---------------------------------------------------------------------------------------------- */
     67 
     68 #if defined(ZYAN_X86) || defined(ZYAN_ARM) || defined(ZYAN_EMSCRIPTEN) || defined(ZYAN_WASM) || defined(ZYAN_PPC)
     69 static ZyanStatus ZydisStringAppendDecU32(ZyanString* string, ZyanU32 value, ZyanU8 padding_length)
     70 {
     71    ZYAN_ASSERT(string);
     72    ZYAN_ASSERT(!string->vector.allocator);
     73 
     74    char buffer[ZYDIS_MAXCHARS_DEC_32];
     75    char *buffer_end = &buffer[ZYDIS_MAXCHARS_DEC_32];
     76    char *buffer_write_pointer = buffer_end;
     77    while (value >= 100)
     78    {
     79        const ZyanU32 value_old = value;
     80        buffer_write_pointer -= 2;
     81        value /= 100;
     82        ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[(value_old - (value * 100)) * 2], 2);
     83    }
     84    buffer_write_pointer -= 2;
     85    ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[value * 2], 2);
     86 
     87    const ZyanUSize offset_odd    = (ZyanUSize)(value < 10);
     88    const ZyanUSize length_number = buffer_end - buffer_write_pointer - offset_odd;
     89    const ZyanUSize length_total  = ZYAN_MAX(length_number, padding_length);
     90    const ZyanUSize length_target = string->vector.size;
     91 
     92    if (string->vector.size + length_total > string->vector.capacity)
     93    {
     94        return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
     95    }
     96 
     97    ZyanUSize offset_write = 0;
     98    if (padding_length > length_number)
     99    {
    100        offset_write = padding_length - length_number;
    101        ZYAN_MEMSET((char*)string->vector.data + length_target - 1, '0', offset_write);
    102    }
    103 
    104    ZYAN_MEMCPY((char*)string->vector.data + length_target + offset_write - 1,
    105        buffer_write_pointer + offset_odd, length_number);
    106    string->vector.size = length_target + length_total;
    107    ZYDIS_STRING_NULLTERMINATE(string);
    108 
    109    return ZYAN_STATUS_SUCCESS;
    110 }
    111 #endif
    112 
    113 static ZyanStatus ZydisStringAppendDecU64(ZyanString* string, ZyanU64 value, ZyanU8 padding_length)
    114 {
    115    ZYAN_ASSERT(string);
    116    ZYAN_ASSERT(!string->vector.allocator);
    117 
    118    char buffer[ZYDIS_MAXCHARS_DEC_64];
    119    char *buffer_end = &buffer[ZYDIS_MAXCHARS_DEC_64];
    120    char *buffer_write_pointer = buffer_end;
    121    while (value >= 100)
    122    {
    123        const ZyanU64 value_old = value;
    124        buffer_write_pointer -= 2;
    125        ZYAN_DIV64(value, 100);
    126        ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[(value_old - (value * 100)) * 2], 2);
    127    }
    128    buffer_write_pointer -= 2;
    129    ZYAN_MEMCPY(buffer_write_pointer, &DECIMAL_LOOKUP[value * 2], 2);
    130 
    131    const ZyanUSize offset_odd    = (ZyanUSize)(value < 10);
    132    const ZyanUSize length_number = buffer_end - buffer_write_pointer - offset_odd;
    133    const ZyanUSize length_total  = ZYAN_MAX(length_number, padding_length);
    134    const ZyanUSize length_target = string->vector.size;
    135 
    136    if (string->vector.size + length_total > string->vector.capacity)
    137    {
    138        return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    139    }
    140 
    141    ZyanUSize offset_write = 0;
    142    if (padding_length > length_number)
    143    {
    144        offset_write = padding_length - length_number;
    145        ZYAN_MEMSET((char*)string->vector.data + length_target - 1, '0', offset_write);
    146    }
    147 
    148    ZYAN_MEMCPY((char*)string->vector.data + length_target + offset_write - 1,
    149        buffer_write_pointer + offset_odd, length_number);
    150    string->vector.size = length_target + length_total;
    151    ZYDIS_STRING_NULLTERMINATE(string);
    152 
    153    return ZYAN_STATUS_SUCCESS;
    154 }
    155 
    156 /* ---------------------------------------------------------------------------------------------- */
    157 /* Hexadecimal                                                                                    */
    158 /* ---------------------------------------------------------------------------------------------- */
    159 
    160 #if defined(ZYAN_X86) || defined(ZYAN_ARM) || defined(ZYAN_EMSCRIPTEN) || defined(ZYAN_WASM) || defined(ZYAN_PPC)
    161 static ZyanStatus ZydisStringAppendHexU32(ZyanString* string, ZyanU32 value, ZyanU8 padding_length,
    162    ZyanBool force_leading_number, ZyanBool uppercase)
    163 {
    164    ZYAN_ASSERT(string);
    165    ZYAN_ASSERT(!string->vector.allocator);
    166 
    167    const ZyanUSize len = string->vector.size;
    168    const ZyanUSize remaining = string->vector.capacity - string->vector.size;
    169 
    170    if (remaining < (ZyanUSize)padding_length)
    171    {
    172        return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    173    }
    174 
    175    if (!value)
    176    {
    177        const ZyanU8 n = (padding_length ? padding_length : 1);
    178 
    179        if (remaining < (ZyanUSize)n)
    180        {
    181            return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    182        }
    183 
    184        ZYAN_MEMSET((char*)string->vector.data + len - 1, '0', n);
    185        string->vector.size = len + n;
    186        ZYDIS_STRING_NULLTERMINATE(string);
    187 
    188        return ZYAN_STATUS_SUCCESS;
    189    }
    190 
    191    ZyanU8 n = 0;
    192    char* buffer = ZYAN_NULL;
    193    for (ZyanI8 i = ZYDIS_MAXCHARS_HEX_32 - 1; i >= 0; --i)
    194    {
    195        const ZyanU8 v = (value >> i * 4) & 0x0F;
    196        if (!n)
    197        {
    198            if (!v)
    199            {
    200                continue;
    201            }
    202            const ZyanU8 zero = force_leading_number && (v > 9) && (padding_length <= i) ? 1 : 0;
    203            if (remaining <= (ZyanUSize)i + zero)
    204            {
    205                return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    206            }
    207            buffer = (char*)string->vector.data + len - 1;
    208            if (zero)
    209            {
    210                buffer[n++] = '0';
    211            }
    212            if (padding_length > i)
    213            {
    214                n = padding_length - i - 1;
    215                ZYAN_MEMSET(buffer, '0', n);
    216            }
    217        }
    218        ZYAN_ASSERT(buffer);
    219        if (uppercase)
    220        {
    221            buffer[n++] = "0123456789ABCDEF"[v];
    222        } else
    223        {
    224            buffer[n++] = "0123456789abcdef"[v];
    225        }
    226    }
    227    string->vector.size = len + n;
    228    ZYDIS_STRING_NULLTERMINATE(string);
    229 
    230    return ZYAN_STATUS_SUCCESS;
    231 }
    232 #endif
    233 
    234 static ZyanStatus ZydisStringAppendHexU64(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
    235    ZyanBool force_leading_number, ZyanBool uppercase)
    236 {
    237    ZYAN_ASSERT(string);
    238    ZYAN_ASSERT(!string->vector.allocator);
    239 
    240    const ZyanUSize len = string->vector.size;
    241    const ZyanUSize remaining = string->vector.capacity - string->vector.size;
    242 
    243    if (remaining < (ZyanUSize)padding_length)
    244    {
    245        return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    246    }
    247 
    248    if (!value)
    249    {
    250        const ZyanU8 n = (padding_length ? padding_length : 1);
    251 
    252        if (remaining < (ZyanUSize)n)
    253        {
    254            return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    255        }
    256 
    257        ZYAN_MEMSET((char*)string->vector.data + len - 1, '0', n);
    258        string->vector.size = len + n;
    259        ZYDIS_STRING_NULLTERMINATE(string);
    260 
    261        return ZYAN_STATUS_SUCCESS;
    262    }
    263 
    264    ZyanU8 n = 0;
    265    char* buffer = ZYAN_NULL;
    266    for (ZyanI8 i = ((value & 0xFFFFFFFF00000000) ?
    267        ZYDIS_MAXCHARS_HEX_64 : ZYDIS_MAXCHARS_HEX_32) - 1; i >= 0; --i)
    268    {
    269        const ZyanU8 v = (value >> i * 4) & 0x0F;
    270        if (!n)
    271        {
    272            if (!v)
    273            {
    274                continue;
    275            }
    276            const ZyanU8 zero = force_leading_number && (v > 9) && (padding_length <= i) ? 1 : 0;
    277            if (remaining <= (ZyanUSize)i + zero)
    278            {
    279                return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
    280            }
    281            buffer = (char*)string->vector.data + len - 1;
    282            if (zero)
    283            {
    284                buffer[n++] = '0';
    285            }
    286            if (padding_length > i)
    287            {
    288                n = padding_length - i - 1;
    289                ZYAN_MEMSET(buffer, '0', n);
    290            }
    291        }
    292        ZYAN_ASSERT(buffer);
    293        if (uppercase)
    294        {
    295            buffer[n++] = "0123456789ABCDEF"[v];
    296        } else
    297        {
    298            buffer[n++] = "0123456789abcdef"[v];
    299        }
    300    }
    301    string->vector.size = len + n;
    302    ZYDIS_STRING_NULLTERMINATE(string);
    303 
    304    return ZYAN_STATUS_SUCCESS;
    305 }
    306 
    307 /* ---------------------------------------------------------------------------------------------- */
    308 
    309 /* ============================================================================================== */
    310 /* Public Functions                                                                               */
    311 /* ============================================================================================== */
    312 
    313 /* ---------------------------------------------------------------------------------------------- */
    314 /* Formatting                                                                                     */
    315 /* ---------------------------------------------------------------------------------------------- */
    316 
    317 ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
    318    const ZyanStringView* prefix, const ZyanStringView* suffix)
    319 {
    320    if (prefix)
    321    {
    322        ZYAN_CHECK(ZydisStringAppend(string, prefix));
    323    }
    324 
    325 #if defined(ZYAN_X64) || defined(ZYAN_AARCH64) || defined(ZYAN_PPC64) || defined(ZYAN_RISCV64) || defined(ZYAN_LOONGARCH)
    326    ZYAN_CHECK(ZydisStringAppendDecU64(string, value, padding_length));
    327 #else
    328    if (value & 0xFFFFFFFF00000000)
    329    {
    330        ZYAN_CHECK(ZydisStringAppendDecU64(string, value, padding_length));
    331    }
    332    ZYAN_CHECK(ZydisStringAppendDecU32(string, (ZyanU32)value, padding_length));
    333 #endif
    334 
    335    if (suffix)
    336    {
    337        return ZydisStringAppend(string, suffix);
    338    }
    339    return ZYAN_STATUS_SUCCESS;
    340 }
    341 
    342 ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length,
    343    ZyanBool force_leading_number, ZyanBool uppercase, const ZyanStringView* prefix,
    344    const ZyanStringView* suffix)
    345 {
    346    if (prefix)
    347    {
    348        ZYAN_CHECK(ZydisStringAppend(string, prefix));
    349    }
    350 
    351 #if defined(ZYAN_X64) || defined(ZYAN_AARCH64) || defined(ZYAN_PPC64) || defined(ZYAN_RISCV64) || defined(ZYAN_LOONGARCH)
    352    ZYAN_CHECK(ZydisStringAppendHexU64(string, value, padding_length, force_leading_number,
    353        uppercase));
    354 #else
    355    if (value & 0xFFFFFFFF00000000)
    356    {
    357        ZYAN_CHECK(ZydisStringAppendHexU64(string, value, padding_length, force_leading_number,
    358            uppercase));
    359    }
    360    else
    361    {
    362        ZYAN_CHECK(ZydisStringAppendHexU32(string, (ZyanU32)value, padding_length,
    363            force_leading_number, uppercase));
    364    }
    365 #endif
    366 
    367    if (suffix)
    368    {
    369        return ZydisStringAppend(string, suffix);
    370    }
    371    return ZYAN_STATUS_SUCCESS;
    372 }
    373 
    374 /* ---------------------------------------------------------------------------------------------- */
    375 
    376 /* ============================================================================================== */