about summary refs log tree commit diff
path: root/converter/pbm/pbmtonokia.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pbmtonokia.c')
-rw-r--r--converter/pbm/pbmtonokia.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/converter/pbm/pbmtonokia.c b/converter/pbm/pbmtonokia.c
index 80b0bd59..4604064a 100644
--- a/converter/pbm/pbmtonokia.c
+++ b/converter/pbm/pbmtonokia.c
@@ -83,7 +83,7 @@ parseCommandLine(int argc, char ** argv,
     MALLOCARRAY_NOFAIL(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0, "fmt",     OPT_STRING, &fmtOpt, 
+    OPTENT3(0, "fmt",     OPT_STRING, &fmtOpt,
             &fmtSpec, 0);
     OPTENT3(0, "net",     OPT_STRING, &netOpt,
             &netSpec, 0);
@@ -135,7 +135,7 @@ parseCommandLine(int argc, char ** argv,
                  "the 120 characters allowed by the format.",
                  (unsigned)strlen(cmdlineP->txt));
 
-    if (argc-1 == 0) 
+    if (argc-1 == 0)
         cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
@@ -180,7 +180,7 @@ convertToHexNol(bit **       const image,
 
     /* header */
     fprintf(ofP, "06050415820000%s00%02X%02X01", networkCode, cols, rows);
-    
+
     /* image */
     for (row = 0; row < rows; ++row) {
         unsigned int col;
@@ -245,7 +245,7 @@ convertToHexNpm(bit **       const image,
                 FILE *       const ofP) {
 
     unsigned int row;
-    
+
     /* header */
     fprintf(ofP, "060504158A0000");
 
@@ -293,7 +293,7 @@ convertToNol(bit **       const image,
     unsigned int row;
     char header[32];
     unsigned int it;
-    
+
     /* header - this is a hack */
 
     header[ 0] = 'N';
@@ -318,7 +318,7 @@ convertToNol(bit **       const image,
     header[19] = 0;
 
     fwrite(header, 20, 1, ofP);
-    
+
     /* image */
     for (row = 0; row < rows; ++row) {
         unsigned int col;
@@ -368,7 +368,7 @@ convertToNgg(bit **       const image,
     header[15] = 0;
 
     fwrite(header, 16, 1, ofP);
-    
+
     /* image */
 
     for (row = 0; row < rows; ++row) {
@@ -395,35 +395,56 @@ convertToNpm(bit **       const image,
              const char * const text,
              FILE *       const ofP) {
 
+    size_t const textLen = text ? strlen(text) : 0;
+
     unsigned int row;
     char header[132];
-    size_t len;
-
-    if (text) 
-        len = strlen(text);
-    else
-        len = 0;
 
     /* header and optional text */
 
-    header[       0] = 'N';
-    header[       1] = 'P';
-    header[       2] = 'M';
-    header[       3] = 0;
-    header[       4] = len;
-    header[       5] = 0;
-    if (text)
-        memcpy(&header[6], text, len);
-    header[ 6 + len] = cols;
-    header[ 7 + len] = rows;
-    header[ 8 + len] = 1;
-    header[ 9 + len] = 1;
-    header[10 + len] = 0; /* unknown */
-
-    assert(10 + len < sizeof(header));
-
-    fwrite(header, 11 + len, 1, ofP);
-    
+    /* Our entry condition is that 'text' be a legal text field, which means
+       no more than 120 characters:
+    */
+    assert(textLen <= 120);
+
+    /* We don't have any specification of this format, but in May 2020, we
+       found what looks like a bug: the memcpy of the text field started at
+       &header[5] (overwriting the previous setting of header[5] and leaving
+       header[6+len-1] not set to anything).  Nobody ever complained about
+       this, so maybe somehow it worked better than the sensible code we have
+       now, where the text field starts in the 7th byte.
+    */
+
+    /* The code below that deliberately avoids using 'text' as an argument to
+       memcpy when 'text' is null looks like it should have no practical
+       effect, because with a zero length memcpy, it shouldn't matter what the
+       from and to arguments are.  But it's logically correct - a null pointer
+       just doesn't point anywhere.  And believe it or not, it has a practical
+       effect - a truly bizarre one.  This code used to be simpler and just
+       pass that null pointer to memcpy, with length 0, and as reported in May
+       2020, a new optimizing compiler caused header[3] to contain random
+       values.  That's right: 3.  Skipping that presumed no-op memcpy stopped
+       the behavior.
+    */
+
+    header[           0] = 'N';
+    header[           1] = 'P';
+    header[           2] = 'M';
+    header[           3] = 0;
+    header[           4] = textLen;
+    header[           5] = 0;
+    if (text)  /* see above */
+        memcpy(&header[6], text, textLen);
+    header[ 6 + textLen] = cols;
+    header[ 7 + textLen] = rows;
+    header[ 8 + textLen] = 1;
+    header[ 9 + textLen] = 1;
+    header[10 + textLen] = 0; /* unknown */
+
+    assert(10 + textLen < sizeof(header));
+
+    fwrite(header, 11 + textLen, 1, ofP);
+
     /* image: stream of bits, each row padded to a byte boundary
        inspired by gnokii/common/gsm-filesystems.c
      */
@@ -453,7 +474,7 @@ convertToNpm(bit **       const image,
 
 
 
-int 
+int
 main(int    argc,
      char * argv[]) {
 
@@ -521,6 +542,6 @@ Testing:
   The data was send with EMI/UCP protocol over TCP/IP.
 
   - 7.6.2001: tested with Nokia 3210: 72x14 Operator Logo
-  - 7.6.2001: tested with Nokia 6210: 72x14 Operator Logo and 
+  - 7.6.2001: tested with Nokia 6210: 72x14 Operator Logo and
               72x14 Group Graphic
 */