Fossil

Check-in [815b4fc4]
Login

Check-in [815b4fc4]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:The variadic function builtin_fossil_js_bundle_or() was using 0 as a sentinel to detect end-of-list, but that isn't equivalent to NULL in a list of pointed-to objects in all C compilers, on all systems. Using a GCC/Clang function attribute to force a warning when 0 is passed instead of NULL, then fixed all resulting warnings. This fixes the SEGV reported in forum post 5feca9c36a on Mac OS X 10.11 with Clang from Xcode 7. Later versions of Clang on macOS don't have this problem, but it's still UB, so fixing it may solve some pain for us later on.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 815b4fc493c433a0e4f8aebe79f4f6b34e1104c33035cc3f8d0c8f43844ba20e
User & Date: wyoung 2020-12-04 18:35:21
Original Comment: The variadic function builtin_fossil_js_bundle_or() was using 0 as a sentinel to detect end-of-list, but that isn't equivalent to NULL in a list of pointed-to objects in all C compilers, on all systems. Using a GCC/Clang function attribute to force a warning when 0 is passed instead of NULL, then fixed all resulting warnings. This fixes the SEGV reported in https://www.fossil-scm.org/forum/forumpost/5feca9c36a on Mac OS X 10.11 with Clang from Xcode 7. Later versions of Clang on macOS don't have this problem, but it's still UB, so fixing it may solve some pain for us later on.
Context
2020-12-14
20:34
Merge from trunk ... (check-in: df330b70 user: george tags: wiki-history)
2020-12-04
19:22
Comment fix to go with previous UB NULL fix. ... (check-in: 4d88ef4f user: wyoung tags: trunk)
18:35
The variadic function builtin_fossil_js_bundle_or() was using 0 as a sentinel to detect end-of-list, but that isn't equivalent to NULL in a list of pointed-to objects in all C compilers, on all systems. Using a GCC/Clang function attribute to force a warning when 0 is passed instead of NULL, then fixed all resulting warnings. This fixes the SEGV reported in forum post 5feca9c36a on Mac OS X 10.11 with Clang from Xcode 7. Later versions of Clang on macOS don't have this problem, but it's still UB, so fixing it may solve some pain for us later on. ... (check-in: 815b4fc4 user: wyoung tags: trunk)
2020-12-03
12:12
Grammar fix ... (check-in: b13c82f0 user: wyoung tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/builtin.c.
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
** expects to "own" the page it is loaded in, and it should be loaded
** as late in the JS-loading process as feasible, ideally bundled (via
** builtin_request_js()) with any other app-/page-specific JS it may
** need.
**
** Example usage:
**
** builtin_fossil_js_bundle_or("dom", "fetch", 0);
**
** In bundled mode, that will (the first time it is called) emit all
** builtin fossil JS APIs and "fulfill" the queue immediately. In
** non-bundled mode it will queue up the "dom" and "fetch" APIs to be
** emitted the next time builtin_fulfill_js_requests() is called.
*/
void builtin_fossil_js_bundle_or( const char * zApi, ... ) {
  static int bundled = 0;
  const char *zArg;
  va_list vargs;

  if(JS_BUNDLED == builtin_get_js_delivery_mode()){
    if(!bundled){
      bundled = 1;
      builtin_emit_fossil_js_once(0);
      builtin_fulfill_js_requests();
    }
    return;
  }
  va_start(vargs,zApi);
  for( zArg = zApi; zArg!=0; (zArg = va_arg (vargs, const char *))){
    if(0==builtin_emit_fossil_js_once(zArg)){
      fossil_fatal("Unknown fossil JS module: %s\n", zArg);
    }
  }
  va_end(vargs);
}







|






|













|






841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
** expects to "own" the page it is loaded in, and it should be loaded
** as late in the JS-loading process as feasible, ideally bundled (via
** builtin_request_js()) with any other app-/page-specific JS it may
** need.
**
** Example usage:
**
** builtin_fossil_js_bundle_or("dom", "fetch", NULL);
**
** In bundled mode, that will (the first time it is called) emit all
** builtin fossil JS APIs and "fulfill" the queue immediately. In
** non-bundled mode it will queue up the "dom" and "fetch" APIs to be
** emitted the next time builtin_fulfill_js_requests() is called.
*/
NULL_SENTINEL void builtin_fossil_js_bundle_or( const char * zApi, ... ) {
  static int bundled = 0;
  const char *zArg;
  va_list vargs;

  if(JS_BUNDLED == builtin_get_js_delivery_mode()){
    if(!bundled){
      bundled = 1;
      builtin_emit_fossil_js_once(0);
      builtin_fulfill_js_requests();
    }
    return;
  }
  va_start(vargs,zApi);
  for( zArg = zApi; zArg!=NULL; (zArg = va_arg (vargs, const char *))){
    if(0==builtin_emit_fossil_js_once(zArg)){
      fossil_fatal("Unknown fossil JS module: %s\n", zArg);
    }
  }
  va_end(vargs);
}
Changes to src/config.h.
243
244
245
246
247
248
249

250
251

252
253

254
255
256
257
258
259
260
#endif

/*
** A marker for functions that never return.
*/
#if defined(__GNUC__) || defined(__clang__)
# define NORETURN __attribute__((__noreturn__))

#elif defined(_MSC_VER) && (_MSC_VER >= 1310)
# define NORETURN __declspec(noreturn)

#else
# define NORETURN

#endif

/*
** Number of elements in an array
*/
#define count(X)      (int)(sizeof(X)/sizeof(X[0]))
#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))







>


>


>







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#endif

/*
** A marker for functions that never return.
*/
#if defined(__GNUC__) || defined(__clang__)
# define NORETURN __attribute__((__noreturn__))
# define NULL_SENTINEL __attribute__((sentinel))
#elif defined(_MSC_VER) && (_MSC_VER >= 1310)
# define NORETURN __declspec(noreturn)
# define NULL_SENTINEL
#else
# define NORETURN
# define NULL_SENTINEL
#endif

/*
** Number of elements in an array
*/
#define count(X)      (int)(sizeof(X)/sizeof(X[0]))
#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
Changes to src/doc.c.
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
** /doc and /wiki pages. None of this implements required
** functionality, just nice-to-haves. Any calls after the first are
** no-ops.
*/
void document_emit_js(void){
  static int once = 0;
  if(0==once++){
    builtin_fossil_js_bundle_or("pikchr", 0);
    style_script_begin(__FILE__,__LINE__);
    CX("window.addEventListener('load', "
       "()=>window.fossil.pikchr.addSrcView(), "
       "false);\n");
    style_script_end();
  }
}







|







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
** /doc and /wiki pages. None of this implements required
** functionality, just nice-to-haves. Any calls after the first are
** no-ops.
*/
void document_emit_js(void){
  static int once = 0;
  if(0==once++){
    builtin_fossil_js_bundle_or("pikchr", NULL);
    style_script_begin(__FILE__,__LINE__);
    CX("window.addEventListener('load', "
       "()=>window.fossil.pikchr.addSrcView(), "
       "false);\n");
    style_script_end();
  }
}
Changes to src/fileedit.c.
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
       "file/check-in combination are discarded.</li>");
    CX("</ul>");
  }
  CX("</div>"/*#fileedit-tab-help*/);

  builtin_fossil_js_bundle_or("fetch", "dom", "tabs", "confirmer",
                              "storage", "popupwidget", "copybutton",
                              "pikchr", 0);
  /*
  ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
  ** used for dynamically toggling certain UI components on and off.
  ** Must come after window.fossil has been intialized and before
  ** fossil.page.fileedit.js. Potential TODO: move this into the
  ** window.fossil bootstrapping so that we don't have to "fulfill"
  ** the JS multiple times.







|







1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
       "file/check-in combination are discarded.</li>");
    CX("</ul>");
  }
  CX("</div>"/*#fileedit-tab-help*/);

  builtin_fossil_js_bundle_or("fetch", "dom", "tabs", "confirmer",
                              "storage", "popupwidget", "copybutton",
                              "pikchr", NULL);
  /*
  ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
  ** used for dynamically toggling certain UI components on and off.
  ** Must come after window.fossil has been intialized and before
  ** fossil.page.fileedit.js. Potential TODO: move this into the
  ** window.fossil bootstrapping so that we don't have to "fulfill"
  ** the JS multiple times.
Changes to src/forum.c.
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

/*
** Emit Forum Javascript which applies (or optionally can apply)
** to all forum-related pages. It does not include page-specific
** code (e.g. "forum.js").
*/
static void forum_emit_js(void){
  builtin_fossil_js_bundle_or("copybutton", "pikchr", 0);
  builtin_request_js("fossil.page.forumpost.js");
}

/*
** WEBPAGE: forumpost
**
** Show a single forum posting. The posting is shown in context with







|







741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

/*
** Emit Forum Javascript which applies (or optionally can apply)
** to all forum-related pages. It does not include page-specific
** code (e.g. "forum.js").
*/
static void forum_emit_js(void){
  builtin_fossil_js_bundle_or("copybutton", "pikchr", NULL);
  builtin_request_js("fossil.page.forumpost.js");
}

/*
** WEBPAGE: forumpost
**
** Show a single forum posting. The posting is shown in context with
Changes to src/info.c.
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
  cgi_printf("%z", htmlize(z, nZ));
  CX("</code></pre></td></tr></tbody></table>\n");
  if(includeJS && !emittedJS){
    emittedJS = 1;
    if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
      builtin_request_js("scroll.js");
    }
    builtin_fossil_js_bundle_or("numbered-lines", 0);
  }
}

/*
** COMMAND: test-line-numbers
**
** Usage: %fossil test-line-numbers FILE ?LN-SPEC?







|







2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
  cgi_printf("%z", htmlize(z, nZ));
  CX("</code></pre></td></tr></tbody></table>\n");
  if(includeJS && !emittedJS){
    emittedJS = 1;
    if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
      builtin_request_js("scroll.js");
    }
    builtin_fossil_js_bundle_or("numbered-lines", NULL);
  }
}

/*
** COMMAND: test-line-numbers
**
** Usage: %fossil test-line-numbers FILE ?LN-SPEC?
Changes to src/pikchrshow.c.
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
        pikchr_process(zContent, pikFlags, 0, &out);
        CX("%b", &out);
        blob_reset(&out);
      } CX("</div>"/*#pikchrshow-output*/);
    } CX("</fieldset>"/*#pikchrshow-output-wrapper*/);
  } CX("</div>"/*sbs-wrapper*/);
  builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget",
                              "storage", "pikchr", 0);
  builtin_request_js("fossil.page.pikchrshow.js");
  builtin_fulfill_js_requests();
  style_finish_page("pikchrshow");
}

/*
** COMMAND: pikchr*







|







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
        pikchr_process(zContent, pikFlags, 0, &out);
        CX("%b", &out);
        blob_reset(&out);
      } CX("</div>"/*#pikchrshow-output*/);
    } CX("</fieldset>"/*#pikchrshow-output-wrapper*/);
  } CX("</div>"/*sbs-wrapper*/);
  builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget",
                              "storage", "pikchr", NULL);
  builtin_request_js("fossil.page.pikchrshow.js");
  builtin_fulfill_js_requests();
  style_finish_page("pikchrshow");
}

/*
** COMMAND: pikchr*
Changes to src/wiki.c.
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
       "sandbox page will fail.</p>");
    CX("<h2>Wiki Name Rules</h2>");
    well_formed_wiki_name_rules();
    CX("</div>"/*#wikiedit-tab-save*/);
  }
  builtin_fossil_js_bundle_or("fetch", "dom", "tabs", "confirmer",
                              "storage", "popupwidget", "copybutton",
                              "pikchr", 0);
  builtin_request_js("sbsdiff.js");
  builtin_request_js("fossil.page.wikiedit.js");
  builtin_fulfill_js_requests();
  /* Dynamically populate the editor... */
  style_script_begin(__FILE__,__LINE__);
  {
    /* Render the current page list to save us an XHR request







|







1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
       "sandbox page will fail.</p>");
    CX("<h2>Wiki Name Rules</h2>");
    well_formed_wiki_name_rules();
    CX("</div>"/*#wikiedit-tab-save*/);
  }
  builtin_fossil_js_bundle_or("fetch", "dom", "tabs", "confirmer",
                              "storage", "popupwidget", "copybutton",
                              "pikchr", NULL);
  builtin_request_js("sbsdiff.js");
  builtin_request_js("fossil.page.wikiedit.js");
  builtin_fulfill_js_requests();
  /* Dynamically populate the editor... */
  style_script_begin(__FILE__,__LINE__);
  {
    /* Render the current page list to save us an XHR request