diff --git a/src/frontend/apiserver/backend/convert_pure.go b/src/frontend/apiserver/backend/convert_pure.go index 535c553b..20d4ca49 100644 --- a/src/frontend/apiserver/backend/convert_pure.go +++ b/src/frontend/apiserver/backend/convert_pure.go @@ -10,7 +10,7 @@ import ( // // |63 62|61 56|55 52|51 20|19 15|14 0| // | TAG | CLUSTER_ID | APISERVER_ID| TIMESTAMP | SEQ_HIGH | ARRAY_IDX | -// | 2 bits | 6 bits | 4 bits | 32 bits | 15 bits | 15 bits | +// | 2 bits | 6 bits | 4 bits | 32 bits | 5 bits | 15 bits | const ( nTagBits = 2 tagShift = 62 @@ -21,8 +21,8 @@ const ( nTimestampBits = 32 timestampShift = 20 nArrayIdxBits = 15 - sequenceHighShift = 15 // mirrors SEQUENCE_HIGH_SHIFT in config.h - nSequenceBits = 30 // mirrors N_SEQUENCE_BITS in config.h + sequenceHighShift = 15 // mirrors SEQUENCE_HIGH_SHIFT in config.h (== N_ARRAY_IDX_BITS) + nSequenceBits = 20 // N_JOBID_BITS(64) - N_CLUSTER_ID_BITS(6) - N_APISERVER_ID_BITS(4) - N_TIMESTAMP_BITS(32) - N_TAG_BITS(2) = 20 tagJobArray = 0x01 // mirrors TAG_JOB_ARRAY in config.h ) diff --git a/src/frontend/apiserver/backend/convert_test.go b/src/frontend/apiserver/backend/convert_test.go index 3eaa847c..b18ff635 100644 --- a/src/frontend/apiserver/backend/convert_test.go +++ b/src/frontend/apiserver/backend/convert_test.go @@ -367,6 +367,42 @@ func TestRawJobToModel_ArrayChildrenShareBaseID(t *testing.T) { } } +// TestExtractArrayBaseID_LargeTimestamp verifies that ExtractArrayBaseID does not +// leak timestamp bits into the extracted sequence when the timestamp field has +// large values. This would fail with nSequenceBits=30 (extracts 15 bits from +// position 15, bleeding into the timestamp at bits 20-51) but passes with the +// correct nSequenceBits=20 (extracts 5 bits from position 15). +func TestExtractArrayBaseID_LargeTimestamp(t *testing.T) { + jobNumber := uint64(7) + arrayIdx := uint64(3) + sequence := jobNumber<