feat(git): add size limits for git operations

- Added MAX_CHERRY_PICK_PATCH_BYTES limit of 100MB for cherry-pick operations
- Added MAX_ACTION_CONTENT_BYTES limit of 100MB for commit action content
- Added MAX_COMMIT_MESSAGE_BYTES limit of 10MB for commit messages
- Added MAX_CHECK_REVISIONS limit of 10,000 for revision checks
- Added MAX_REBASE_COMMITS limit of 10,000 for rebase operations
- Added MAX_REBASE_PATCH_BYTES limit of 100MB for rebase patches
- Added MAX_RESOLUTION_CONTENT_BYTES limit of 100MB for merge conflict resolutions
- Added MAX_REVERT_PATCH_BYTES limit of 100MB for revert operations
- Return InvalidArgument error when size limits are exceeded with descriptive messages
This commit is contained in:
zhenyi
2026-06-12 12:59:47 +08:00
parent 934858bebf
commit 293102e5f2
6 changed files with 78 additions and 0 deletions
+16
View File
@@ -3,6 +3,9 @@ use crate::commit::create_commit::command_ok;
use crate::error::{GitError, GitResult};
use crate::pb::{RebaseRequest, RebaseResult, rebase_result};
const MAX_REBASE_COMMITS: usize = 10_000;
const MAX_REBASE_PATCH_BYTES: usize = 100 * 1024 * 1024;
impl GitBare {
pub fn rebase(&self, request: RebaseRequest) -> GitResult<RebaseResult> {
let branch = request.branch.clone();
@@ -68,6 +71,13 @@ impl GitBare {
.map(String::from)
.collect();
if commits.len() > MAX_REBASE_COMMITS {
return Err(GitError::InvalidArgument(format!(
"too many commits to rebase ({} > max {MAX_REBASE_COMMITS})",
commits.len()
)));
}
if commits.is_empty() {
return Ok(RebaseResult {
status: rebase_result::Status::RebaseResultStatusAlreadyUpToDate as i32,
@@ -150,6 +160,12 @@ impl GitBare {
.unchecked()
.run()?;
let patch_data = command_ok(diff)?;
if patch_data.len() > MAX_REBASE_PATCH_BYTES {
return Err(GitError::InvalidArgument(format!(
"rebase patch too large for {commit_hex} ({} bytes, max {MAX_REBASE_PATCH_BYTES})",
patch_data.len()
)));
}
let apply = duct::cmd(
"git",
+15
View File
@@ -3,6 +3,8 @@ use crate::commit::create_commit::command_ok;
use crate::error::{GitError, GitResult};
use crate::pb::{MergeResult, ResolveMergeConflictsRequest, merge_result};
const MAX_RESOLUTION_CONTENT_BYTES: usize = 100 * 1024 * 1024;
impl GitBare {
pub fn resolve_merge_conflicts(
&self,
@@ -50,8 +52,21 @@ impl GitBare {
.run()?;
command_ok(read_tree)?;
const MAX_RESOLUTIONS_COUNT: usize = 10_000;
if request.resolutions.len() > MAX_RESOLUTIONS_COUNT {
return Err(GitError::InvalidArgument(format!(
"too many resolutions (max {MAX_RESOLUTIONS_COUNT})"
)));
}
for resolution in &request.resolutions {
crate::sanitize::validate_file_path(&resolution.path)?;
if resolution.content.len() > MAX_RESOLUTION_CONTENT_BYTES {
return Err(GitError::InvalidArgument(format!(
"resolution content too large ({} bytes, max {MAX_RESOLUTION_CONTENT_BYTES})",
resolution.content.len()
)));
}
let hash = duct::cmd(
"git",
["--git-dir", bare.as_str(), "hash-object", "-w", "--stdin"],