rugged 0.21.2 → 0.21.3

Sign up to get free protection for your applications and to get access to all the features.
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
+ }