From 6604c5ce924cd5e8151b349fa39b82a9687bd111 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira Date: Sat, 5 Jul 2025 12:11:40 +0200 Subject: [PATCH] Make strndup smaller, safer, faster First implementation was doing: - strdup (without checking result!) - strlen - terminate - realloc New one does: - malloc to shortest +1 - strncpy - terminate --- libsrc/common/strndup.s | 75 ++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/libsrc/common/strndup.s b/libsrc/common/strndup.s index ce81fc1cc..5dcfe806b 100644 --- a/libsrc/common/strndup.s +++ b/libsrc/common/strndup.s @@ -4,53 +4,50 @@ ; char* __fastcall__ strndup (const char* S, size_t maxlen); ; - .importzp ptr4, c_sp - .import _strdup, _strlen, pushax, popax, _realloc + .importzp tmp1, tmp2, ptr2 + .import _strncpy, _strlen, _malloc + .import pushax, popax, incsp2, incax1, swapstk + .import ___errno .export _strndup -_strndup: - sta maxlen ; Remember maxlen - stx maxlen+1 + .include "errno.inc" - jsr popax ; Duplicate string - jsr _strdup - jsr pushax ; Remember result +.proc _strndup + sta tmp1 ; Remember maxlen + stx tmp1+1 - jsr _strlen ; Check length, - cpx maxlen+1 - bcc out ; Return directly if < maxlen + jsr popax ; Get string + jsr pushax ; Keep it in TOS + + jsr _strlen ; Get string length, + cpx tmp1+1 ; Compare to max, + bcc alloc bne :+ - cmp maxlen - bcc out + cmp tmp1 + bcc alloc -: ldy #$00 ; Otherwise, point to end of string, - lda maxlen - clc - adc (c_sp),y - sta ptr4 - lda maxlen+1 - iny - adc (c_sp),y - sta ptr4+1 +: lda tmp1 ; Use maxlen if shorter + ldx tmp1+1 - dey ; Cut it short, - tya - sta (ptr4),y +alloc: jsr incax1 ; Add 1 for terminator + jsr _malloc ; Allocate output + cpx #$00 ; Check allocation + beq errmem - ldx maxlen+1 ; And finally, realloc to maxlen+1 - ldy maxlen - iny - tya - bne :+ - inx -: jsr _realloc ; TOS still contains result - ; We consider realloc will not fail, - ; as the block shrinks. - jsr pushax ; push/pop for size optimisation -out: - jmp popax + jsr swapstk ; Put dest in TOS and get string back + jsr pushax ; Put src in TOS + lda tmp1 ; Get length for strncpy + ldx tmp1+1 - .bss + jsr _strncpy ; Copy + pha ; Terminate + lda #$00 + sta (ptr2),y + pla + rts -maxlen: .res 2 +errmem: ldy #ENOMEM + sty ___errno + jmp incsp2 ; Pop string and return +.endproc