@@ -636,6 +636,8 @@ static int fsck_tree(const struct object_id *tree_oid,
636636 retval += report (options , tree_oid , OBJ_TREE ,
637637 FSCK_MSG_MAILMAP_SYMLINK ,
638638 ".mailmap is a symlink" );
639+ oidset_insert (& options -> symlink_targets_found ,
640+ entry_oid );
639641 }
640642
641643 if ((backslash = strchr (name , '\\' ))) {
@@ -1228,6 +1230,56 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
12281230 }
12291231 }
12301232
1233+ if (oidset_contains (& options -> symlink_targets_found , oid )) {
1234+ const char * ptr = buf ;
1235+ const struct object_id * reported = NULL ;
1236+
1237+ oidset_insert (& options -> symlink_targets_done , oid );
1238+
1239+ if (!buf || size > PATH_MAX ) {
1240+ /*
1241+ * A missing buffer here is a sign that the caller found the
1242+ * blob too gigantic to load into memory. Let's just consider
1243+ * that an error.
1244+ */
1245+ return report (options , oid , OBJ_BLOB ,
1246+ FSCK_MSG_SYMLINK_TARGET_LENGTH ,
1247+ "symlink target too long" );
1248+ }
1249+
1250+ while (!reported && ptr ) {
1251+ const char * p = ptr ;
1252+ char c , * slash = strchrnul (ptr , '/' );
1253+ char * backslash = memchr (ptr , '\\' , slash - ptr );
1254+
1255+ c = * slash ;
1256+ * slash = '\0' ;
1257+
1258+ while (!reported && backslash ) {
1259+ * backslash = '\0' ;
1260+ if (is_ntfs_dotgit (p ))
1261+ ret |= report (options , reported = oid , OBJ_BLOB ,
1262+ FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR ,
1263+ "symlink target points to git dir" );
1264+ * backslash = '\\' ;
1265+ p = backslash + 1 ;
1266+ backslash = memchr (p , '\\' , slash - p );
1267+ }
1268+ if (!reported && is_ntfs_dotgit (p ))
1269+ ret |= report (options , reported = oid , OBJ_BLOB ,
1270+ FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR ,
1271+ "symlink target points to git dir" );
1272+
1273+ if (!reported && is_hfs_dotgit (ptr ))
1274+ ret |= report (options , reported = oid , OBJ_BLOB ,
1275+ FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR ,
1276+ "symlink target points to git dir" );
1277+
1278+ * slash = c ;
1279+ ptr = c ? slash + 1 : NULL ;
1280+ }
1281+ }
1282+
12311283 return ret ;
12321284}
12331285
@@ -1319,6 +1371,10 @@ int fsck_finish(struct fsck_options *options)
13191371 FSCK_MSG_GITATTRIBUTES_MISSING , FSCK_MSG_GITATTRIBUTES_BLOB ,
13201372 options , ".gitattributes" );
13211373
1374+ ret |= fsck_blobs (& options -> symlink_targets_found , & options -> symlink_targets_done ,
1375+ FSCK_MSG_SYMLINK_TARGET_MISSING , FSCK_MSG_SYMLINK_TARGET_BLOB ,
1376+ options , "<symlink-target>" );
1377+
13221378 return ret ;
13231379}
13241380
0 commit comments