| 723 | } |
| 724 | |
| 725 | static PyObject *read_python_string(Buffer *buffer) { |
| 726 | Error error; |
| 727 | const uint64_t header = buffer->read_var_uint64(error); |
| 728 | if (FORY_PREDICT_FALSE(!error.ok())) { |
| 729 | set_buffer_error(error); |
| 730 | return nullptr; |
| 731 | } |
| 732 | const uint64_t size64 = header >> 2U; |
| 733 | if (FORY_PREDICT_FALSE(size64 > std::numeric_limits<uint32_t>::max())) { |
| 734 | PyErr_SetString(PyExc_OverflowError, |
| 735 | "string length too large for fastpath decoding"); |
| 736 | return nullptr; |
| 737 | } |
| 738 | const uint32_t size = static_cast<uint32_t>(size64); |
| 739 | const uint32_t encoding = static_cast<uint32_t>(header & 0b11ULL); |
| 740 | if (size == 0) { |
| 741 | return PyUnicode_FromStringAndSize("", 0); |
| 742 | } |
| 743 | |
| 744 | uint32_t reader_index = buffer->reader_index(); |
| 745 | if (FORY_PREDICT_FALSE(size > buffer->size() - reader_index)) { |
| 746 | if (FORY_PREDICT_FALSE(!buffer->ensure_readable(size, error))) { |
| 747 | set_buffer_error(error); |
| 748 | return nullptr; |
| 749 | } |
| 750 | reader_index = buffer->reader_index(); |
| 751 | } |
| 752 | const char *data = |
| 753 | reinterpret_cast<const char *>(buffer->data() + reader_index); |
| 754 | buffer->reader_index(reader_index + size); |
| 755 | |
| 756 | if (encoding == 0) { |
| 757 | return PyUnicode_DecodeLatin1(data, static_cast<Py_ssize_t>(size), |
| 758 | "strict"); |
| 759 | } |
| 760 | if (encoding == 1) { |
| 761 | if (FORY_PREDICT_FALSE((size & 1U) != 0U)) { |
| 762 | PyErr_SetString(PyExc_ValueError, "invalid utf16 string length"); |
| 763 | return nullptr; |
| 764 | } |
| 765 | const auto *utf16_data = reinterpret_cast<const uint16_t *>(data); |
| 766 | if (utf16_has_surrogate_pairs(utf16_data, |
| 767 | static_cast<size_t>(size >> 1U))) { |
| 768 | int byteorder = -1; // little-endian |
| 769 | return PyUnicode_DecodeUTF16(data, static_cast<Py_ssize_t>(size), |
| 770 | "strict", &byteorder); |
| 771 | } |
| 772 | return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, data, |
| 773 | static_cast<Py_ssize_t>(size >> 1U)); |
| 774 | } |
| 775 | if (encoding == 2) { |
| 776 | return PyUnicode_DecodeUTF8(data, static_cast<Py_ssize_t>(size), "strict"); |
| 777 | } |
| 778 | PyErr_Format(PyExc_ValueError, "unsupported string encoding tag: %u", |
| 779 | encoding); |
| 780 | return nullptr; |
| 781 | } |
| 782 |
no test coverage detected