Fossil

Check-in [6c19baa09b]
Login

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

Overview
Comment:Moved is_fossil_ckout_db_name() from db.c to file.c and renamed it filename_is_ckout_db(). Integrated the check into manifest_parse(), but testing it requires temporarily #if'ing out the Z-card check, which is one of the first validations.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | reject-ckout-db
Files: files | file ages | folders
SHA3-256: 6c19baa09b6316cbe6d2b41ead20cfa4cb21eba798ce29227ef5d17fa1c19ab5
User & Date: stephan 2020-08-17 16:10:33.298
Context
2020-08-17
17:34
Added checks of (-wal, -shm, -journal) db suffixes. check-in: 4ed1a294ff user: stephan tags: reject-ckout-db
16:10
Moved is_fossil_ckout_db_name() from db.c to file.c and renamed it filename_is_ckout_db(). Integrated the check into manifest_parse(), but testing it requires temporarily #if'ing out the Z-card check, which is one of the first validations. check-in: 6c19baa09b user: stephan tags: reject-ckout-db
15:40
switch/case style tweak, per request. check-in: 9784e5cdab user: stephan tags: reject-ckout-db
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/db.c.
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
  ** column to vfile and vmerge and changing the UNIQUE index on vmerge into
  ** a PRIMARY KEY that includes the new mhash column.  However, we must have
  ** the repository database at hand in order to do the migration, so that
  ** step is deferred. */
  return 1;
}

/*
** Returns true if the given filename ends with any of fossil's
** checkout database filenames: _FOSSIL_ or .fslckout. Specifically,
** it returns 1 if it's an exact match and 2 if it's the tail match
** on a longer input.
**
** zFilename must, for efficiency's sake, be a
** canonicalized/normalized name, e.g. using only '/' as directory
** separators.
**
** nFilename must be the strlen of zFilename. If it is negative,
** strlen() is used to calculate it.
*/
int is_fossil_ckout_db_name(const char *zFilename, int nFilename){
  const char *zEnd;

  if(nFilename>=0 && nFilename<8/*strlen _FOSSIL_*/) return 0;
  else if(nFilename<0) nFilename = (int)strlen(zFilename);
  if(nFilename<8) return 0;
  zEnd = zFilename + nFilename;
  switch(zEnd[-1]){
    case '_': {
      return fossil_strcmp("_FOSSIL_", &zEnd[-8])
        ? 0 : (8==nFilename ? 1 : ('/'==zEnd[-9] ? 2 : 0));
    }
    case 't': {
      return (nFilename<9
              || '.'!=zEnd[-9]
              || fossil_strcmp(".fslckout", &zEnd[-9]))
        ? 0 : (9==nFilename ? 1 : ('/'==zEnd[-10] ? 2 : 0));
    }
    default:
      return 0;
  }
}

/*
** COMMAND: test-is-ckout-db
**
** Usage: %fossil test-is-ckout-db FILENAMES...
**
** Passes each given name to is_fossil_ckout_db_name() and outputs one
** line per file: the result value of that function followed by the
** name.
*/
void test_is_ckout_name_cmd(void){
  int i;

  if(g.argc<3){
    usage("FILENAME_1 [...FILENAME_N]");
  }
  for( i = 2; i < g.argc; ++i ){
    const int check = is_fossil_ckout_db_name(g.argv[i], -1);
    fossil_print("%d %s\n", check, g.argv[i]);
  }
}

/*
** Locate the root directory of the local repository tree.  The root
** directory is found by searching for a file named "_FOSSIL_" or ".fslckout"
** that contains a valid repository database.
**
** For legacy, also look for ".fos".  The use of ".fos" is deprecated
** since "fos" has negative connotations in Hungarian, we are told.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1703
1704
1705
1706
1707
1708
1709

























































1710
1711
1712
1713
1714
1715
1716
  ** column to vfile and vmerge and changing the UNIQUE index on vmerge into
  ** a PRIMARY KEY that includes the new mhash column.  However, we must have
  ** the repository database at hand in order to do the migration, so that
  ** step is deferred. */
  return 1;
}


























































/*
** Locate the root directory of the local repository tree.  The root
** directory is found by searching for a file named "_FOSSIL_" or ".fslckout"
** that contains a valid repository database.
**
** For legacy, also look for ".fos".  The use of ".fos" is deprecated
** since "fos" has negative connotations in Hungarian, we are told.
Changes to src/file.c.
2406
2407
2408
2409
2410
2411
2412





























































** special case, if it ends with a period then a pointer to the
** terminating NUL byte is returned.
*/
const char * file_extension(const char *zFileName){
  const char * zExt = zFileName ? strrchr(zFileName, '.') : 0;
  return zExt ? &zExt[1] : 0;
}




































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
** special case, if it ends with a period then a pointer to the
** terminating NUL byte is returned.
*/
const char * file_extension(const char *zFileName){
  const char * zExt = zFileName ? strrchr(zFileName, '.') : 0;
  return zExt ? &zExt[1] : 0;
}

/*
** Returns true if the given filename ends with any of fossil's
** checkout database filenames: _FOSSIL_ or .fslckout. Specifically,
** it returns 1 if it's an exact match and 2 if it's the tail match
** on a longer input.
**
** zFilename must, for efficiency's sake, be a
** canonicalized/normalized name, e.g. using only '/' as directory
** separators.
**
** nFilename must be the strlen of zFilename. If it is negative,
** strlen() is used to calculate it.
**
** TODO: https://fossil-scm.org/sec2020/info/972cf9c302f5413f
** TL;DR: check for the -wal, -shm, -journal suffix forms of the db
** names.
*/
int filename_is_ckout_db(const char *zFilename, int nFilename){
  const char *zEnd;

  if(nFilename>=0 && nFilename<8/*strlen _FOSSIL_*/) return 0;
  else if(nFilename<0) nFilename = (int)strlen(zFilename);
  if(nFilename<8) return 0;
  zEnd = zFilename + nFilename;
  switch(zEnd[-1]){
    case '_': {
      return fossil_strcmp("_FOSSIL_", &zEnd[-8])
        ? 0 : (8==nFilename ? 1 : ('/'==zEnd[-9] ? 2 : 0));
    }
    case 't': {
      return (nFilename<9
              || '.'!=zEnd[-9]
              || fossil_strcmp(".fslckout", &zEnd[-9]))
        ? 0 : (9==nFilename ? 1 : ('/'==zEnd[-10] ? 2 : 0));
    }
    default:
      return 0;
  }
}

/*
** COMMAND: test-is-ckout-db
**
** Usage: %fossil test-is-ckout-db FILENAMES...
**
** Passes each given name to filename_is_ckout_db() and outputs one
** line per file: the result value of that function followed by the
** name.
*/
void test_is_ckout_name_cmd(void){
  int i;

  if(g.argc<3){
    usage("FILENAME_1 [...FILENAME_N]");
  }
  for( i = 2; i < g.argc; ++i ){
    const int check = filename_is_ckout_db(g.argv[i], -1);
    fossil_print("%d %s\n", check, g.argv[i]);
  }
}
Changes to src/manifest.c.
479
480
481
482
483
484
485



486
487
488
489






490
491
492
493
494
495
496
  if( n<10 || z[0]<'A' || z[0]>'Z' || z[1]!=' ' ){
    blob_reset(pContent);
    blob_appendf(pErr, "line 1 not recognized");
    return 0;
  }
  /* Then verify the Z-card.
  */



  if( verify_z_card(z, n, pErr)==2 ){
    blob_reset(pContent);
    return 0;
  }







  /* Allocate a Manifest object to hold the parsed control artifact.
  */
  p = fossil_malloc( sizeof(*p) );
  memset(p, 0, sizeof(*p));
  memcpy(&p->content, pContent, sizeof(p->content));
  p->rid = rid;







>
>
>




>
>
>
>
>
>







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  if( n<10 || z[0]<'A' || z[0]>'Z' || z[1]!=' ' ){
    blob_reset(pContent);
    blob_appendf(pErr, "line 1 not recognized");
    return 0;
  }
  /* Then verify the Z-card.
  */
#if 1
  /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
     for card-related syntax errors. */
  if( verify_z_card(z, n, pErr)==2 ){
    blob_reset(pContent);
    return 0;
  }
#else
#warning ACHTUNG - z-card check is disabled for testing purposes.
  if(0 && verify_z_card(NULL, 0, NULL)){
    /*avoid unused static func error*/
  }
#endif

  /* Allocate a Manifest object to hold the parsed control artifact.
  */
  p = fossil_malloc( sizeof(*p) );
  memset(p, 0, sizeof(*p));
  memcpy(&p->content, pContent, sizeof(p->content));
  p->rid = rid;
620
621
622
623
624
625
626


627
628
629
630
631
632
633
      case 'F': {
        char *zName, *zPerm, *zPriorName;
        zName = next_token(&x,0);
        if( zName==0 ) SYNTAX("missing filename on F-card");
        defossilize(zName);
        if( !file_is_simple_pathname_nonstrict(zName) ){
          SYNTAX("F-card filename is not a simple path");


        }
        zUuid = next_token(&x, &sz);
        if( p->zBaseline==0 || zUuid!=0 ){
          if( !hname_validate(zUuid,sz) ){
            SYNTAX("F-card hash invalid");
          }
        }







>
>







629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
      case 'F': {
        char *zName, *zPerm, *zPriorName;
        zName = next_token(&x,0);
        if( zName==0 ) SYNTAX("missing filename on F-card");
        defossilize(zName);
        if( !file_is_simple_pathname_nonstrict(zName) ){
          SYNTAX("F-card filename is not a simple path");
        }else if( filename_is_ckout_db(zName,-1) ){
          SYNTAX("F-card contains reserved name of a checkout db.");
        }
        zUuid = next_token(&x, &sz);
        if( p->zBaseline==0 || zUuid!=0 ){
          if( !hname_validate(zUuid,sz) ){
            SYNTAX("F-card hash invalid");
          }
        }