aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2024-05-02 18:05:21 +0200
committerMattias EngdegÄrd2025-08-24 10:28:27 +0200
commit308e3ab1dbd9633b843541af55d77c82b725df02 (patch)
tree7036ce2267ad670d95e1b2702f4554e97395e233 /src/alloc.c
parent230ed1f9b6da42515735970c370424c37bda5d59 (diff)
downloademacs-308e3ab1dbd9633b843541af55d77c82b725df02.tar.gz
emacs-308e3ab1dbd9633b843541af55d77c82b725df02.zip
Disallow string data resizing (bug#79784)
Only allow string mutation that is certain not to require string data to be resized and reallocated: writing bytes into a unibyte string, and changing ASCII to ASCII in a multibyte string. This ensures that mutation will never transform a unibyte string to multibyte, that the size of a string in bytes never changes, and that the byte offsets of characters remain the same. Most importantly, it removes a long-standing obstacle to reform of string representation and allow for future performance improvements. * src/data.c (Faset): Disallow resizing string mutation. * src/fns.c (clear_string_char_byte_cache): * src/alloc.c (resize_string_data): Remove. * test/src/data-tests.el (data-aset-string): New test. * test/lisp/subr-tests.el (subr--subst-char-in-string): Skip error cases. * test/src/alloc-tests.el (aset-nbytes-change): Remove test that is no longer relevant. * doc/lispref/strings.texi (Modifying Strings): * doc/lispref/sequences.texi (Array Functions): * doc/lispref/text.texi (Substitution): Update manual. * etc/NEWS: Announce.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c50
1 files changed, 0 insertions, 50 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 07ca8474bf3..9ace6f01856 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1815,56 +1815,6 @@ allocate_string_data (struct Lisp_String *s,
1815 tally_consing (needed); 1815 tally_consing (needed);
1816} 1816}
1817 1817
1818/* Reallocate multibyte STRING data when a single character is replaced.
1819 The character is at byte offset CIDX_BYTE in the string.
1820 The character being replaced is CLEN bytes long,
1821 and the character that will replace it is NEW_CLEN bytes long.
1822 Return the address where the caller should store the new character. */
1823
1824unsigned char *
1825resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
1826 int clen, int new_clen)
1827{
1828 eassume (STRING_MULTIBYTE (string));
1829 sdata *old_sdata = SDATA_OF_STRING (XSTRING (string));
1830 ptrdiff_t nchars = SCHARS (string);
1831 ptrdiff_t nbytes = SBYTES (string);
1832 ptrdiff_t new_nbytes = nbytes + (new_clen - clen);
1833 unsigned char *data = SDATA (string);
1834 unsigned char *new_charaddr;
1835
1836 if (sdata_size (nbytes) == sdata_size (new_nbytes))
1837 {
1838 /* No need to reallocate, as the size change falls within the
1839 alignment slop. */
1840 XSTRING (string)->u.s.size_byte = new_nbytes;
1841#ifdef GC_CHECK_STRING_BYTES
1842 SDATA_NBYTES (old_sdata) = new_nbytes;
1843#endif
1844 new_charaddr = data + cidx_byte;
1845 memmove (new_charaddr + new_clen, new_charaddr + clen,
1846 nbytes - (cidx_byte + (clen - 1)));
1847 }
1848 else
1849 {
1850 allocate_string_data (XSTRING (string), nchars, new_nbytes, false, false);
1851 unsigned char *new_data = SDATA (string);
1852 new_charaddr = new_data + cidx_byte;
1853 memcpy (new_charaddr + new_clen, data + cidx_byte + clen,
1854 nbytes - (cidx_byte + clen));
1855 memcpy (new_data, data, cidx_byte);
1856
1857 /* Mark old string data as free by setting its string back-pointer
1858 to null, and record the size of the data in it. */
1859 SDATA_NBYTES (old_sdata) = nbytes;
1860 old_sdata->string = NULL;
1861 }
1862
1863 clear_string_char_byte_cache ();
1864
1865 return new_charaddr;
1866}
1867
1868 1818
1869/* Sweep and compact strings. */ 1819/* Sweep and compact strings. */
1870 1820