From 14c8708b6524c0d21f4bcf0b755cc86e29a1bb35 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 7 May 2024 19:04:29 +0000 Subject: closes [a858d95f4bfddafb]: adjust word-token pointer after possible realloc --- generic/tclClockFmt.c | 2 ++ tests/clock.test | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 154c8ee..fdac4fb 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -2307,6 +2307,7 @@ ClockGetOrParseScanFormat( wordTok->tokWord.start = p; wordTok->map = &ScnWordTokenMap; AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); + wordTok = tok - 1; tokCnt++; } if (isspace(UCHAR(*p))) { @@ -3344,6 +3345,7 @@ ClockGetOrParseFmtFormat( wordTok->tokWord.start = p; wordTok->map = &FmtWordTokenMap; AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); + wordTok = tok - 1; tokCnt++; } p = Tcl_UtfNext(p); diff --git a/tests/clock.test b/tests/clock.test index 8072a68..ef41ad5 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -375,6 +375,10 @@ test clock-1.9 "clock arguments: option doubly present" { list [catch {clock format 0 -gmt 1 -gmt 0} result] $result } {1 {bad option "-gmt": doubly present}} +test clock-1.10 {clock format: text with token (bug [a858d95f4bfddafb])} { + clock format 0 -format text(%d) -gmt 1 +} {text(01)} + # BEGIN testcases2 # Test formatting of Gregorian year, month, day, all formats @@ -18924,6 +18928,10 @@ test clock-6.22.20 {Greedy match (second space wins as date-time separator)} { clock format [clock scan "111 2 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1 } {Sun Jan 02 13:12:00 GMT 2011} +test clock-6.23 {clock scan: text with token (bug [a858d95f4bfddafb])} { + clock scan {text(01)} -format text(%d) -gmt 1 -base 0 +} 0 + test clock-7.1 {Julian Day} { clock scan 0 -format %J -gmt true -- cgit v0.12 From 550e07034cc781c7cc5a15e5dd5977c8f9be16c8 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 7 May 2024 20:09:14 +0000 Subject: code review (optimization by parse of word tokens in clock format) --- generic/tclClockFmt.c | 67 +++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index fdac4fb..b08dc72 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -2139,16 +2139,13 @@ EstimateTokenCount( return ++tokcnt; } -#define AllocTokenInChain(tok, chain, tokCnt, type) \ - if (++(tok) >= (chain) + (tokCnt)) { \ - chain = (type)attemptckrealloc((char *)(chain), \ +#define AllocTokenInChain(tok, chain, tokCnt, type) \ + if (++(tok) >= (chain) + (tokCnt)) { \ + chain = (type)ckrealloc((char *)(chain), \ (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \ - if ((chain) == NULL) { \ - goto done; \ - } \ - (tok) = (chain) + (tokCnt); \ - (tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \ - } \ + (tok) = (chain) + (tokCnt); \ + (tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \ + } \ memset(tok, 0, sizeof(*(tok))); /* @@ -2281,7 +2278,7 @@ ClockGetOrParseScanFormat( continue; } default: - if (*p == ' ' || isspace(UCHAR(*p))) { + if (isspace(UCHAR(*p))) { tok->map = &ScnSpaceTokenMap; tok->tokWord.start = p++; while (p < e && isspace(UCHAR(*p))) { @@ -2295,29 +2292,34 @@ ClockGetOrParseScanFormat( tokCnt++; continue; } - word_tok: - { + word_tok: + { ClockScanToken *wordTok = tok; if (tok > scnTok && (tok - 1)->map == &ScnWordTokenMap) { + /* further with previous word token */ wordTok = tok - 1; - } - /* new word token */ - if (wordTok == tok) { + } else { + /* new word token */ wordTok->tokWord.start = p; wordTok->map = &ScnWordTokenMap; + } + + do { + if (isspace(UCHAR(*p))) { + fss->scnSpaceCount++; + } + p = Tcl_UtfNext(p); + } while (p < e && *p != '%'); + wordTok->tokWord.end = p; + + if (wordTok == tok) { AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); - wordTok = tok - 1; tokCnt++; } - if (isspace(UCHAR(*p))) { - fss->scnSpaceCount++; } - p = Tcl_UtfNext(p); - wordTok->tokWord.end = p; break; } - } } /* calculate end distance value for each tokens */ @@ -2349,9 +2351,8 @@ ClockGetOrParseScanFormat( fss->scnTok = scnTok; fss->scnTokC = tokCnt; } - done: - Tcl_MutexUnlock(&ClockFmtMutex); + Tcl_MutexUnlock(&ClockFmtMutex); return fss; } @@ -3335,24 +3336,28 @@ ClockGetOrParseFmtFormat( continue; } default: - word_tok: { + word_tok: + { ClockFormatToken *wordTok = tok; if (tok > fmtTok && (tok - 1)->map == &FmtWordTokenMap) { wordTok = tok - 1; - } - if (wordTok == tok) { + } else { wordTok->tokWord.start = p; wordTok->map = &FmtWordTokenMap; + } + do { + p = Tcl_UtfNext(p); + } while (p < e && *p != '%'); + wordTok->tokWord.end = p; + + if (wordTok == tok) { AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); - wordTok = tok - 1; tokCnt++; } - p = Tcl_UtfNext(p); - wordTok->tokWord.end = p; + } break; } - } } /* correct count of real used tokens and free mem if desired @@ -3368,7 +3373,7 @@ ClockGetOrParseFmtFormat( fss->fmtTok = fmtTok; fss->fmtTokC = tokCnt; } - done: + Tcl_MutexUnlock(&ClockFmtMutex); return fss; } -- cgit v0.12