summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--FatPkg/EnhancedFatDxe/FileSpace.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/FatPkg/EnhancedFatDxe/FileSpace.c b/FatPkg/EnhancedFatDxe/FileSpace.c
index 1254cd68b5..50391b75b8 100644
--- a/FatPkg/EnhancedFatDxe/FileSpace.c
+++ b/FatPkg/EnhancedFatDxe/FileSpace.c
@@ -467,7 +467,7 @@ FatGrowEof (
ClusterCount = 0;
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
- if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
+ if (Cluster < FAT_MIN_CLUSTER || Cluster > Volume->MaxCluster + 1) {
DEBUG (
(EFI_D_INIT | EFI_D_ERROR,
@@ -509,6 +509,11 @@ FatGrowEof (
goto Done;
}
+ if (NewCluster < FAT_MIN_CLUSTER || NewCluster > Volume->MaxCluster + 1) {
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Done;
+ }
+
if (LastCluster != 0) {
FatSetFatEntry (Volume, LastCluster, NewCluster);
} else {
@@ -518,12 +523,21 @@ FatGrowEof (
LastCluster = NewCluster;
CurSize += 1;
+
+ //
+ // Terminate the cluster list
+ //
+ // Note that we must do this EVERY time we allocate a cluster, because
+ // FatAllocateCluster scans the FAT looking for a free cluster and
+ // "LastCluster" is no longer free! Usually, FatAllocateCluster will
+ // start looking with the cluster after "LastCluster"; however, when
+ // there is only one free cluster left, it will find "LastCluster"
+ // a second time. There are other, less predictable scenarios
+ // where this could happen, as well.
+ //
+ FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
+ OFile->FileLastCluster = LastCluster;
}
- //
- // Terminate the cluster list
- //
- FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
- OFile->FileLastCluster = LastCluster;
}
OFile->FileSize = (UINTN) NewSizeInBytes;
@@ -603,7 +617,7 @@ FatOFilePosition (
Cluster = FatGetFatEntry (Volume, Cluster);
}
- if (Cluster < FAT_MIN_CLUSTER) {
+ if (Cluster < FAT_MIN_CLUSTER || Cluster > Volume->MaxCluster + 1) {
return EFI_VOLUME_CORRUPTED;
}