rugged 0.21.2 → 0.21.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7fd19143d7ae79c19dcc780edd7399e0b96c677b
4
- data.tar.gz: c2e501d2d3525acc5a3a2297bc3726fc0c3465f8
3
+ metadata.gz: 2276d0e49569313a6d31cf68b90615f8d1a2c4a8
4
+ data.tar.gz: 30ebcb87a56c02eee6742a86b0eff38ef91b2a9c
5
5
  SHA512:
6
- metadata.gz: 2b6f3fb73a8d64f10b2dcac66dc7bc6a27c8257bf72f9d2d02b7d3179bb24a096a36593c87b420cfd31e889425c72b725d81f551907115ef717101716bb4f390
7
- data.tar.gz: 991a7b7aaa258c7fe858dedde2694493ce4af466e61ea42935fac3afe3ceaa1b80298f345f83cb82ee237256968ffe45faabfc182402d349ded4665bcf794424
6
+ metadata.gz: 84a1ce59332b2d6494c3e1f3be71fde89bbb27a12839b0ac35ab673e02977c9fefbc8443815e4dff34574b65e588dec22aaded418660c3323b04c03a137bb79b
7
+ data.tar.gz: b3d6bc7c00b28e4a9255f1826bb35e7b7b66d5cf3a325f3f51f355cf50016f544dc9bc30c3c7e2eb5a6cb501f977e3e8a8c4b76862a82881f6b09eb6674f9264
@@ -1,3 +1,3 @@
1
1
  module Rugged
2
- Version = VERSION = '0.21.2'
2
+ Version = VERSION = '0.21.3'
3
3
  end
@@ -7,10 +7,10 @@
7
7
  #ifndef INCLUDE_git_version_h__
8
8
  #define INCLUDE_git_version_h__
9
9
 
10
- #define LIBGIT2_VERSION "0.21.2"
10
+ #define LIBGIT2_VERSION "0.21.3"
11
11
  #define LIBGIT2_VER_MAJOR 0
12
12
  #define LIBGIT2_VER_MINOR 21
13
- #define LIBGIT2_VER_REVISION 2
13
+ #define LIBGIT2_VER_REVISION 3
14
14
 
15
15
  #define LIBGIT2_SOVERSION 21
16
16
 
@@ -1078,6 +1078,30 @@ done:
1078
1078
  return error;
1079
1079
  }
1080
1080
 
1081
+ static int checkout_verify_paths(
1082
+ git_repository *repo,
1083
+ int action,
1084
+ git_diff_delta *delta)
1085
+ {
1086
+ unsigned int flags = GIT_PATH_REJECT_DEFAULTS | GIT_PATH_REJECT_DOT_GIT;
1087
+
1088
+ if (action & CHECKOUT_ACTION__REMOVE) {
1089
+ if (!git_path_isvalid(repo, delta->old_file.path, flags)) {
1090
+ giterr_set(GITERR_CHECKOUT, "Cannot remove invalid path '%s'", delta->old_file.path);
1091
+ return -1;
1092
+ }
1093
+ }
1094
+
1095
+ if (action & ~CHECKOUT_ACTION__REMOVE) {
1096
+ if (!git_path_isvalid(repo, delta->new_file.path, flags)) {
1097
+ giterr_set(GITERR_CHECKOUT, "Cannot checkout to invalid path '%s'", delta->old_file.path);
1098
+ return -1;
1099
+ }
1100
+ }
1101
+
1102
+ return 0;
1103
+ }
1104
+
1081
1105
  static int checkout_get_actions(
1082
1106
  uint32_t **actions_ptr,
1083
1107
  size_t **counts_ptr,
@@ -1111,7 +1135,9 @@ static int checkout_get_actions(
1111
1135
  }
1112
1136
 
1113
1137
  git_vector_foreach(deltas, i, delta) {
1114
- error = checkout_action(&act, data, delta, workdir, &wditem, &pathspec);
1138
+ if ((error = checkout_action(&act, data, delta, workdir, &wditem, &pathspec)) == 0)
1139
+ error = checkout_verify_paths(data->repo, act, delta);
1140
+
1115
1141
  if (error != 0)
1116
1142
  goto fail;
1117
1143
 
@@ -76,6 +76,8 @@ static struct map_data _cvar_maps[] = {
76
76
  {"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT },
77
77
  {"core.safecrlf", _cvar_map_safecrlf, ARRAY_SIZE(_cvar_map_safecrlf), GIT_SAFE_CRLF_DEFAULT},
78
78
  {"core.logallrefupdates", NULL, 0, GIT_LOGALLREFUPDATES_DEFAULT },
79
+ {"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT },
80
+ {"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT },
79
81
  };
80
82
 
81
83
  int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar)
@@ -756,23 +756,35 @@ void git_index_entry__init_from_stat(
756
756
  entry->file_size = st->st_size;
757
757
  }
758
758
 
759
- static git_index_entry *index_entry_alloc(const char *path)
759
+ static int index_entry_create(
760
+ git_index_entry **out,
761
+ git_repository *repo,
762
+ const char *path)
760
763
  {
761
764
  size_t pathlen = strlen(path);
762
- struct entry_internal *entry =
763
- git__calloc(sizeof(struct entry_internal) + pathlen + 1, 1);
764
- if (!entry)
765
- return NULL;
765
+ struct entry_internal *entry;
766
+
767
+ if (!git_path_isvalid(repo, path,
768
+ GIT_PATH_REJECT_DEFAULTS | GIT_PATH_REJECT_DOT_GIT)) {
769
+ giterr_set(GITERR_INDEX, "Invalid path: '%s'", path);
770
+ return -1;
771
+ }
772
+
773
+ entry = git__calloc(sizeof(struct entry_internal) + pathlen + 1, 1);
774
+ GITERR_CHECK_ALLOC(entry);
766
775
 
767
776
  entry->pathlen = pathlen;
768
777
  memcpy(entry->path, path, pathlen);
769
778
  entry->entry.path = entry->path;
770
779
 
771
- return (git_index_entry *)entry;
780
+ *out = (git_index_entry *)entry;
781
+ return 0;
772
782
  }
773
783
 
774
784
  static int index_entry_init(
775
- git_index_entry **entry_out, git_index *index, const char *rel_path)
785
+ git_index_entry **entry_out,
786
+ git_index *index,
787
+ const char *rel_path)
776
788
  {
777
789
  int error = 0;
778
790
  git_index_entry *entry = NULL;
@@ -784,14 +796,17 @@ static int index_entry_init(
784
796
  "Could not initialize index entry. "
785
797
  "Index is not backed up by an existing repository.");
786
798
 
799
+ if (index_entry_create(&entry, INDEX_OWNER(index), rel_path) < 0)
800
+ return -1;
801
+
787
802
  /* write the blob to disk and get the oid and stat info */
788
803
  error = git_blob__create_from_paths(
789
804
  &oid, &st, INDEX_OWNER(index), NULL, rel_path, 0, true);
790
- if (error < 0)
791
- return error;
792
805
 
793
- entry = index_entry_alloc(rel_path);
794
- GITERR_CHECK_ALLOC(entry);
806
+ if (error < 0) {
807
+ index_entry_free(entry);
808
+ return error;
809
+ }
795
810
 
796
811
  entry->id = oid;
797
812
  git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
@@ -847,7 +862,10 @@ static void index_entry_cpy(git_index_entry *tgt, const git_index_entry *src)
847
862
  tgt->path = tgt_path; /* reset to existing path data */
848
863
  }
849
864
 
850
- static int index_entry_dup(git_index_entry **out, const git_index_entry *src)
865
+ static int index_entry_dup(
866
+ git_index_entry **out,
867
+ git_repository *repo,
868
+ const git_index_entry *src)
851
869
  {
852
870
  git_index_entry *entry;
853
871
 
@@ -856,11 +874,11 @@ static int index_entry_dup(git_index_entry **out, const git_index_entry *src)
856
874
  return 0;
857
875
  }
858
876
 
859
- *out = entry = index_entry_alloc(src->path);
860
- GITERR_CHECK_ALLOC(entry);
877
+ if (index_entry_create(&entry, repo, src->path) < 0)
878
+ return -1;
861
879
 
862
880
  index_entry_cpy(entry, src);
863
-
881
+ *out = entry;
864
882
  return 0;
865
883
  }
866
884
 
@@ -1125,7 +1143,7 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
1125
1143
  return -1;
1126
1144
  }
1127
1145
 
1128
- if ((ret = index_entry_dup(&entry, source_entry)) < 0 ||
1146
+ if ((ret = index_entry_dup(&entry, INDEX_OWNER(index), source_entry)) < 0 ||
1129
1147
  (ret = index_insert(index, &entry, 1)) < 0)
1130
1148
  return ret;
1131
1149
 
@@ -1245,9 +1263,9 @@ int git_index_conflict_add(git_index *index,
1245
1263
 
1246
1264
  assert (index);
1247
1265
 
1248
- if ((ret = index_entry_dup(&entries[0], ancestor_entry)) < 0 ||
1249
- (ret = index_entry_dup(&entries[1], our_entry)) < 0 ||
1250
- (ret = index_entry_dup(&entries[2], their_entry)) < 0)
1266
+ if ((ret = index_entry_dup(&entries[0], INDEX_OWNER(index), ancestor_entry)) < 0 ||
1267
+ (ret = index_entry_dup(&entries[1], INDEX_OWNER(index), our_entry)) < 0 ||
1268
+ (ret = index_entry_dup(&entries[2], INDEX_OWNER(index), their_entry)) < 0)
1251
1269
  goto on_error;
1252
1270
 
1253
1271
  for (i = 0; i < 3; i++) {
@@ -1764,7 +1782,10 @@ static int read_conflict_names(git_index *index, const char *buffer, size_t size
1764
1782
  }
1765
1783
 
1766
1784
  static size_t read_entry(
1767
- git_index_entry **out, const void *buffer, size_t buffer_size)
1785
+ git_index_entry **out,
1786
+ git_index *index,
1787
+ const void *buffer,
1788
+ size_t buffer_size)
1768
1789
  {
1769
1790
  size_t path_length, entry_size;
1770
1791
  const char *path_ptr;
@@ -1828,7 +1849,7 @@ static size_t read_entry(
1828
1849
 
1829
1850
  entry.path = (char *)path_ptr;
1830
1851
 
1831
- if (index_entry_dup(out, &entry) < 0)
1852
+ if (index_entry_dup(out, INDEX_OWNER(index), &entry) < 0)
1832
1853
  return 0;
1833
1854
 
1834
1855
  return entry_size;
@@ -1929,7 +1950,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
1929
1950
  /* Parse all the entries */
1930
1951
  for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
1931
1952
  git_index_entry *entry;
1932
- size_t entry_size = read_entry(&entry, buffer, buffer_size);
1953
+ size_t entry_size = read_entry(&entry, index, buffer, buffer_size);
1933
1954
 
1934
1955
  /* 0 bytes read means an object corruption */
1935
1956
  if (entry_size == 0) {
@@ -2268,6 +2289,7 @@ int git_index_entry_stage(const git_index_entry *entry)
2268
2289
  }
2269
2290
 
2270
2291
  typedef struct read_tree_data {
2292
+ git_index *index;
2271
2293
  git_vector *old_entries;
2272
2294
  git_vector *new_entries;
2273
2295
  git_vector_cmp entry_cmp;
@@ -2287,8 +2309,8 @@ static int read_tree_cb(
2287
2309
  if (git_buf_joinpath(&path, root, tentry->filename) < 0)
2288
2310
  return -1;
2289
2311
 
2290
- entry = index_entry_alloc(path.ptr);
2291
- GITERR_CHECK_ALLOC(entry);
2312
+ if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr) < 0)
2313
+ return -1;
2292
2314
 
2293
2315
  entry->mode = tentry->attr;
2294
2316
  entry->id = tentry->oid;
@@ -2328,6 +2350,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
2328
2350
 
2329
2351
  git_vector_set_cmp(&entries, index->entries._cmp); /* match sort */
2330
2352
 
2353
+ data.index = index;
2331
2354
  data.old_entries = &index->entries;
2332
2355
  data.new_entries = &entries;
2333
2356
  data.entry_cmp = index->entries_search;
@@ -2440,7 +2463,7 @@ int git_index_add_all(
2440
2463
  break;
2441
2464
 
2442
2465
  /* make the new entry to insert */
2443
- if ((error = index_entry_dup(&entry, wd)) < 0)
2466
+ if ((error = index_entry_dup(&entry, INDEX_OWNER(index), wd)) < 0)
2444
2467
  break;
2445
2468
 
2446
2469
  entry->id = blobid;
@@ -7,6 +7,7 @@
7
7
  #include "common.h"
8
8
  #include "path.h"
9
9
  #include "posix.h"
10
+ #include "repository.h"
10
11
  #ifdef GIT_WIN32
11
12
  #include "win32/posix.h"
12
13
  #include "win32/w32_util.h"
@@ -1155,3 +1156,258 @@ int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path)
1155
1156
 
1156
1157
  return 0;
1157
1158
  }
1159
+
1160
+ /* Reject paths like AUX or COM1, or those versions that end in a dot or
1161
+ * colon. ("AUX." or "AUX:")
1162
+ */
1163
+ GIT_INLINE(bool) verify_dospath(
1164
+ const char *component,
1165
+ size_t len,
1166
+ const char dospath[3],
1167
+ bool trailing_num)
1168
+ {
1169
+ size_t last = trailing_num ? 4 : 3;
1170
+
1171
+ if (len < last || git__strncasecmp(component, dospath, 3) != 0)
1172
+ return true;
1173
+
1174
+ if (trailing_num && !git__isdigit(component[3]))
1175
+ return true;
1176
+
1177
+ return (len > last &&
1178
+ component[last] != '.' &&
1179
+ component[last] != ':');
1180
+ }
1181
+
1182
+ static int32_t next_hfs_char(const char **in, size_t *len)
1183
+ {
1184
+ while (*len) {
1185
+ int32_t codepoint;
1186
+ int cp_len = git__utf8_iterate((const uint8_t *)(*in), (int)(*len), &codepoint);
1187
+ if (cp_len < 0)
1188
+ return -1;
1189
+
1190
+ (*in) += cp_len;
1191
+ (*len) -= cp_len;
1192
+
1193
+ /* these code points are ignored completely */
1194
+ switch (codepoint) {
1195
+ case 0x200c: /* ZERO WIDTH NON-JOINER */
1196
+ case 0x200d: /* ZERO WIDTH JOINER */
1197
+ case 0x200e: /* LEFT-TO-RIGHT MARK */
1198
+ case 0x200f: /* RIGHT-TO-LEFT MARK */
1199
+ case 0x202a: /* LEFT-TO-RIGHT EMBEDDING */
1200
+ case 0x202b: /* RIGHT-TO-LEFT EMBEDDING */
1201
+ case 0x202c: /* POP DIRECTIONAL FORMATTING */
1202
+ case 0x202d: /* LEFT-TO-RIGHT OVERRIDE */
1203
+ case 0x202e: /* RIGHT-TO-LEFT OVERRIDE */
1204
+ case 0x206a: /* INHIBIT SYMMETRIC SWAPPING */
1205
+ case 0x206b: /* ACTIVATE SYMMETRIC SWAPPING */
1206
+ case 0x206c: /* INHIBIT ARABIC FORM SHAPING */
1207
+ case 0x206d: /* ACTIVATE ARABIC FORM SHAPING */
1208
+ case 0x206e: /* NATIONAL DIGIT SHAPES */
1209
+ case 0x206f: /* NOMINAL DIGIT SHAPES */
1210
+ case 0xfeff: /* ZERO WIDTH NO-BREAK SPACE */
1211
+ continue;
1212
+ }
1213
+
1214
+ /* fold into lowercase -- this will only fold characters in
1215
+ * the ASCII range, which is perfectly fine, because the
1216
+ * git folder name can only be composed of ascii characters
1217
+ */
1218
+ return tolower(codepoint);
1219
+ }
1220
+ return 0; /* NULL byte -- end of string */
1221
+ }
1222
+
1223
+ static bool verify_dotgit_hfs(const char *path, size_t len)
1224
+ {
1225
+ if (next_hfs_char(&path, &len) != '.' ||
1226
+ next_hfs_char(&path, &len) != 'g' ||
1227
+ next_hfs_char(&path, &len) != 'i' ||
1228
+ next_hfs_char(&path, &len) != 't' ||
1229
+ next_hfs_char(&path, &len) != 0)
1230
+ return true;
1231
+
1232
+ return false;
1233
+ }
1234
+
1235
+ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size_t len)
1236
+ {
1237
+ const char *shortname = NULL;
1238
+ size_t i, start, shortname_len = 0;
1239
+
1240
+ /* See if the repo has a custom shortname (not "GIT~1") */
1241
+ if (repo &&
1242
+ (shortname = git_repository__8dot3_name(repo)) &&
1243
+ shortname != git_repository__8dot3_default)
1244
+ shortname_len = strlen(shortname);
1245
+
1246
+ if (len >= 4 && strncasecmp(path, ".git", 4) == 0)
1247
+ start = 4;
1248
+ else if (len >= git_repository__8dot3_default_len &&
1249
+ strncasecmp(path, git_repository__8dot3_default, git_repository__8dot3_default_len) == 0)
1250
+ start = git_repository__8dot3_default_len;
1251
+ else if (shortname_len && len >= shortname_len &&
1252
+ strncasecmp(path, shortname, shortname_len) == 0)
1253
+ start = shortname_len;
1254
+ else
1255
+ return true;
1256
+
1257
+ /* Reject paths beginning with ".git\" */
1258
+ if (path[start] == '\\')
1259
+ return false;
1260
+
1261
+ for (i = start; i < len; i++) {
1262
+ if (path[i] != ' ' && path[i] != '.')
1263
+ return true;
1264
+ }
1265
+
1266
+ return false;
1267
+ }
1268
+
1269
+ GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
1270
+ {
1271
+ if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')
1272
+ return false;
1273
+
1274
+ if ((flags & GIT_PATH_REJECT_SLASH) && c == '/')
1275
+ return false;
1276
+
1277
+ if (flags & GIT_PATH_REJECT_NT_CHARS) {
1278
+ if (c < 32)
1279
+ return false;
1280
+
1281
+ switch (c) {
1282
+ case '<':
1283
+ case '>':
1284
+ case ':':
1285
+ case '"':
1286
+ case '|':
1287
+ case '?':
1288
+ case '*':
1289
+ return false;
1290
+ }
1291
+ }
1292
+
1293
+ return true;
1294
+ }
1295
+
1296
+ /*
1297
+ * We fundamentally don't like some paths when dealing with user-inputted
1298
+ * strings (in checkout or ref names): we don't want dot or dot-dot
1299
+ * anywhere, we want to avoid writing weird paths on Windows that can't
1300
+ * be handled by tools that use the non-\\?\ APIs, we don't want slashes
1301
+ * or double slashes at the end of paths that can make them ambiguous.
1302
+ *
1303
+ * For checkout, we don't want to recurse into ".git" either.
1304
+ */
1305
+ static bool verify_component(
1306
+ git_repository *repo,
1307
+ const char *component,
1308
+ size_t len,
1309
+ unsigned int flags)
1310
+ {
1311
+ if (len == 0)
1312
+ return false;
1313
+
1314
+ if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
1315
+ len == 1 && component[0] == '.')
1316
+ return false;
1317
+
1318
+ if ((flags & GIT_PATH_REJECT_TRAVERSAL) &&
1319
+ len == 2 && component[0] == '.' && component[1] == '.')
1320
+ return false;
1321
+
1322
+ if ((flags & GIT_PATH_REJECT_TRAILING_DOT) && component[len-1] == '.')
1323
+ return false;
1324
+
1325
+ if ((flags & GIT_PATH_REJECT_TRAILING_SPACE) && component[len-1] == ' ')
1326
+ return false;
1327
+
1328
+ if ((flags & GIT_PATH_REJECT_TRAILING_COLON) && component[len-1] == ':')
1329
+ return false;
1330
+
1331
+ if (flags & GIT_PATH_REJECT_DOS_PATHS) {
1332
+ if (!verify_dospath(component, len, "CON", false) ||
1333
+ !verify_dospath(component, len, "PRN", false) ||
1334
+ !verify_dospath(component, len, "AUX", false) ||
1335
+ !verify_dospath(component, len, "NUL", false) ||
1336
+ !verify_dospath(component, len, "COM", true) ||
1337
+ !verify_dospath(component, len, "LPT", true))
1338
+ return false;
1339
+ }
1340
+
1341
+ if (flags & GIT_PATH_REJECT_DOT_GIT_HFS &&
1342
+ !verify_dotgit_hfs(component, len))
1343
+ return false;
1344
+
1345
+ if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS &&
1346
+ !verify_dotgit_ntfs(repo, component, len))
1347
+ return false;
1348
+
1349
+ if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
1350
+ (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1351
+ (flags & GIT_PATH_REJECT_DOT_GIT) &&
1352
+ len == 4 &&
1353
+ component[0] == '.' &&
1354
+ (component[1] == 'g' || component[1] == 'G') &&
1355
+ (component[2] == 'i' || component[2] == 'I') &&
1356
+ (component[3] == 't' || component[3] == 'T'))
1357
+ return false;
1358
+
1359
+ return true;
1360
+ }
1361
+
1362
+ GIT_INLINE(unsigned int) dotgit_flags(
1363
+ git_repository *repo,
1364
+ unsigned int flags)
1365
+ {
1366
+ int protectHFS = 0, protectNTFS = 0;
1367
+
1368
+ #ifdef __APPLE__
1369
+ protectHFS = 1;
1370
+ #endif
1371
+
1372
+ #ifdef GIT_WIN32
1373
+ protectNTFS = 1;
1374
+ #endif
1375
+
1376
+ if (repo && !protectHFS)
1377
+ git_repository__cvar(&protectHFS, repo, GIT_CVAR_PROTECTHFS);
1378
+ if (protectHFS)
1379
+ flags |= GIT_PATH_REJECT_DOT_GIT_HFS;
1380
+
1381
+ if (repo && !protectNTFS)
1382
+ git_repository__cvar(&protectNTFS, repo, GIT_CVAR_PROTECTNTFS);
1383
+ if (protectNTFS)
1384
+ flags |= GIT_PATH_REJECT_DOT_GIT_NTFS;
1385
+
1386
+ return flags;
1387
+ }
1388
+
1389
+ bool git_path_isvalid(
1390
+ git_repository *repo,
1391
+ const char *path,
1392
+ unsigned int flags)
1393
+ {
1394
+ const char *start, *c;
1395
+
1396
+ /* Upgrade the ".git" checks based on platform */
1397
+ if ((flags & GIT_PATH_REJECT_DOT_GIT))
1398
+ flags = dotgit_flags(repo, flags);
1399
+
1400
+ for (start = c = path; *c; c++) {
1401
+ if (!verify_char(*c, flags))
1402
+ return false;
1403
+
1404
+ if (*c == '/') {
1405
+ if (!verify_component(repo, start, (c - start), flags))
1406
+ return false;
1407
+
1408
+ start = c+1;
1409
+ }
1410
+ }
1411
+
1412
+ return verify_component(repo, start, (c - start), flags);
1413
+ }