| 948 | } |
| 949 | |
| 950 | static int fsck_commit(const struct object_id *oid, |
| 951 | const char *buffer, unsigned long size, |
| 952 | struct fsck_options *options) |
| 953 | { |
| 954 | struct object_id tree_oid, parent_oid; |
| 955 | unsigned author_count; |
| 956 | int err; |
| 957 | const char *buffer_begin = buffer; |
| 958 | const char *buffer_end = buffer + size; |
| 959 | const char *p; |
| 960 | |
| 961 | /* |
| 962 | * We _must_ stop parsing immediately if this reports failure, as the |
| 963 | * memory safety of the rest of the function depends on it. See the |
| 964 | * comment above the definition of verify_headers() for more details. |
| 965 | */ |
| 966 | if (verify_headers(buffer, size, oid, OBJ_COMMIT, options)) |
| 967 | return -1; |
| 968 | |
| 969 | if (buffer >= buffer_end || !skip_prefix(buffer, "tree ", &buffer)) |
| 970 | return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_TREE, "invalid format - expected 'tree' line"); |
| 971 | if (parse_oid_hex_algop(buffer, &tree_oid, &p, options->repo->hash_algo) || *p != '\n') { |
| 972 | err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_TREE_SHA1, "invalid 'tree' line format - bad sha1"); |
| 973 | if (err) |
| 974 | return err; |
| 975 | } |
| 976 | buffer = p + 1; |
| 977 | while (buffer < buffer_end && skip_prefix(buffer, "parent ", &buffer)) { |
| 978 | if (parse_oid_hex_algop(buffer, &parent_oid, &p, options->repo->hash_algo) || *p != '\n') { |
| 979 | err = report(options, oid, OBJ_COMMIT, FSCK_MSG_BAD_PARENT_SHA1, "invalid 'parent' line format - bad sha1"); |
| 980 | if (err) |
| 981 | return err; |
| 982 | } |
| 983 | buffer = p + 1; |
| 984 | } |
| 985 | author_count = 0; |
| 986 | while (buffer < buffer_end && skip_prefix(buffer, "author ", &buffer)) { |
| 987 | author_count++; |
| 988 | err = fsck_ident(&buffer, buffer_end, oid, OBJ_COMMIT, options); |
| 989 | if (err) |
| 990 | return err; |
| 991 | } |
| 992 | if (author_count < 1) |
| 993 | err = report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_AUTHOR, "invalid format - expected 'author' line"); |
| 994 | else if (author_count > 1) |
| 995 | err = report(options, oid, OBJ_COMMIT, FSCK_MSG_MULTIPLE_AUTHORS, "invalid format - multiple 'author' lines"); |
| 996 | if (err) |
| 997 | return err; |
| 998 | if (buffer >= buffer_end || !skip_prefix(buffer, "committer ", &buffer)) |
| 999 | return report(options, oid, OBJ_COMMIT, FSCK_MSG_MISSING_COMMITTER, "invalid format - expected 'committer' line"); |
| 1000 | err = fsck_ident(&buffer, buffer_end, oid, OBJ_COMMIT, options); |
| 1001 | if (err) |
| 1002 | return err; |
| 1003 | if (memchr(buffer_begin, '\0', size)) { |
| 1004 | err = report(options, oid, OBJ_COMMIT, FSCK_MSG_NUL_IN_COMMIT, |
| 1005 | "NUL byte in the commit object body"); |
| 1006 | if (err) |
| 1007 | return err; |
no test coverage detected