From aeb6bca35ab93bae035f8ff0cc8a70669a3ece92 Mon Sep 17 00:00:00 2001 From: nick black Date: Tue, 11 Jun 2024 09:02:18 -0400 Subject: [PATCH] ncsixel_as_rgba: fix processing following '$' waveplate pointed out that we needed to move to STATE_WANT_DATA rather than STATE_WANT_HASH following a '$' in sixel text. this was breaking ncsixel_as_rgba() for larger sixels, for which we now have a unit test. Closes #2784 --- NEWS.md | 4 ++++ src/lib/sixel.h | 20 ++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index bd4c90602..306bab97c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,10 @@ rearrangements of Notcurses. * We now normalize the return of `nl_langinfo()` according to the behavior of glibc's `_nl_normalize_charset()`, supporting some atypical synonyms of `UTF-8`. + * Fixed a bug in `ncsixel_as_rgba()` (called by `ncvisual_from_sixel()`) + that broke loading of sixels having more than 12 rows (sixel generation + from images worked fine). Thanks, waveplate! + * Reject illegal geometries in `ncvisual_from_*()`. * 3.0.9 (2022-12-10) * Eliminated infinite loop in `ncplane_move_family_above()`. diff --git a/src/lib/sixel.h b/src/lib/sixel.h index 4df1e7f52..b95a18379 100644 --- a/src/lib/sixel.h +++ b/src/lib/sixel.h @@ -10,6 +10,10 @@ extern "C" { #include "logging.h" uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ + if(!leny || !lenx){ + logerror("null sixel geometry"); + return NULL; + } #define MAXCOLORS 65535 // cast is necessary for c++ callers uint32_t* rgba = (uint32_t*)calloc(leny * lenx, sizeof(*rgba)); @@ -26,7 +30,7 @@ uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ // transparent line (the only possible colorless line). while(*sx != '#' && *sx != '-'){ if(!*sx){ - logerror("expected octothorpe/hyphen, got eol\n"); + logerror("expected octothorpe/hyphen, got eol"); return NULL; } ++sx; @@ -56,12 +60,12 @@ uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ }else if('#' == *sx){ state = STATE_WANT_COLOR; }else{ - logerror("expected octothorpe, got %u\n", *sx); + logerror("expected octothorpe, got %u", *sx); goto err; } }else if(state == STATE_WANT_COLOR){ if(!isdigit(*sx)){ - logerror("expected digit, got %u\n", *sx); + logerror("expected digit, got %u", *sx); goto err; } color = 0; @@ -84,12 +88,12 @@ uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ } }else if(state == STATE_WANT_COLORSPACE){ if('2' != *(sx++)){ - logerror("expected '2', got %u\n", *sx); + logerror("expected '2', got %u", *sx); goto err; } //fprintf(stderr, "SX: %u 0x%02x %c\n", *sx, *sx, *sx); if(';' != *(sx++)){ - logerror("expected semicolon, got %u\n", *sx); + logerror("expected semicolon, got %u", *sx); goto err; } //fprintf(stderr, "SX: %u 0x%02x %c\n", *sx, *sx, *sx); @@ -100,7 +104,7 @@ uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ ++sx; }while(isdigit(*sx)); if(';' != *(sx++)){ - logerror("expected semicolon, got %u\n", *sx); + logerror("expected semicolon, got %u", *sx); goto err; } //fprintf(stderr, "SX: %u 0x%02x %c\n", *sx, *sx, *sx); @@ -112,7 +116,7 @@ uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ ++sx; }while(isdigit(*sx)); if(';' != *(sx++)){ - logerror("expected semicolon, got %u\n", *sx); + logerror("expected semicolon, got %u", *sx); goto err; } //fprintf(stderr, "SX: %u 0x%02x %c\n", *sx, *sx, *sx); @@ -153,7 +157,7 @@ uint32_t* ncsixel_as_rgba(const char *sx, unsigned leny, unsigned lenx){ --sx; }else if(*sx == '$'){ x = 0; - state = STATE_WANT_HASH; + state = STATE_WANT_DATA; }else if(*sx == '-'){ x = 0; y += 6;