{"record":{"id":"690a628d9508b64b","repo":"grpc/grpc-go","slug":"mem-allocating-slice-of-size-2-d-is-not-possible","errorCode":null,"errorMessage":"mem: allocating slice of size 2^%d is not possible","messagePattern":"mem: allocating slice of size 2\\^(.+?) is not possible","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mem/buffer_pool.go","lineNumber":105,"sourceCode":"\nfunc newBinaryTiered(sizedPoolFactory func(int) bufferPool, fallbackPool bufferPool, powerOfTwoExponents ...uint8) (*BinaryTieredBufferPool, error) {\n\tslices.Sort(powerOfTwoExponents)\n\tpowerOfTwoExponents = slices.Compact(powerOfTwoExponents)\n\n\t// Determine the maximum exponent we need to support. This depends on the\n\t// word size (32-bit vs 64-bit).\n\tmaxExponent := uintSize - 2\n\tindexOfNextLargestBit := slices.Repeat([]int{-1}, maxExponent+1)\n\tindexOfPreviousLargestBit := slices.Repeat([]int{-1}, maxExponent+1)\n\n\tmaxTier := 0\n\tpools := make([]bufferPool, 0, len(powerOfTwoExponents))\n\n\tfor i, exp := range powerOfTwoExponents {\n\t\t// Allocating slices of size > 2^maxExponent isn't possible on\n\t\t// maxExponent-bit machines.\n\t\tif int(exp) > maxExponent {\n\t\t\treturn nil, fmt.Errorf(\"mem: allocating slice of size 2^%d is not possible\", exp)\n\t\t}\n\t\ttierSize := 1 << exp\n\t\tpools = append(pools, sizedPoolFactory(tierSize))\n\t\tmaxTier = max(maxTier, tierSize)\n\n\t\t// Map the exact power of 2 to this pool index.\n\t\tindexOfNextLargestBit[exp] = i\n\t\tindexOfPreviousLargestBit[exp] = i\n\t}\n\n\t// Fill gaps for Get() (Next Largest)\n\t// We iterate backwards. If current is empty, take the value from the right (larger).\n\tfor i := maxExponent - 1; i >= 0; i-- {\n\t\tif indexOfNextLargestBit[i] == -1 {\n\t\t\tindexOfNextLargestBit[i] = indexOfNextLargestBit[i+1]\n\t\t}\n\t}\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/mem/buffer_pool.go#L87-L123","documentation":"BinaryTieredBufferPool is constructed from power-of-two exponents; at buffer_pool.go:104 each exponent is bounds-checked against maxExponent = uintSize - 2 (62 on 64-bit, 30 on 32-bit platforms). Requesting a tier of size 2^exp where exp exceeds this limit is impossible to allocate as a Go slice on that architecture, so NewBinaryTieredBufferPool/NewDirtyBinaryTieredBufferPool returns an error instead of panicking. The exponent, not the byte count, is printed.","triggerScenarios":"Triggered by NewBinaryTieredBufferPool(powerOfTwoExponents...) or NewDirtyBinaryTieredBufferPool(...) when one of the supplied uint8 exponents is greater than maxExponent (uintSize-2). For example passing 63 on a 64-bit build (2^63 bytes) or any value > 30 on a 32-bit build.","commonSituations":"A caller mistakenly passes the desired byte size (e.g. 4096, 16384) instead of the exponent (12, 14), or hard-codes an exponent that is valid on 64-bit but breaks 32-bit builds, or derives the exponent from attacker/config-controlled input without clamping.","solutions":["Confirm you are passing exponents (log2 of the byte size), not raw byte sizes: pass 12 for 4 KiB, 14 for 16 KiB, 20 for 1 MiB.","Clamp/validate the exponent against your platform's maxExponent: keep exponents <= 30 for 32-bit-safe code, <= 62 for 64-bit.","If you genuinely need very large pooled buffers, fall back to a SimpleBufferPool/NopBufferPool that allocates on demand rather than a fixed tier.","Unit-test pool construction with the exact exponents your config permits."],"exampleFix":"// before: passing byte size as exponent\n//   pool, err := mem.NewBinaryTieredBufferPool(4096, 16384)\n//   // err: allocating slice of size 2^4096 is not possible\n\n// after: pass exponents\n//   pool, err := mem.NewBinaryTieredBufferPool(12, 14) // 4 KiB, 16 KiB","handlingStrategy":"validation","validationCode":"package main\n\nimport (\n\t\"fmt\"\n\t\"math/bits\"\n)\n\n// validExponent returns nil if exp can index a Go slice on this platform.\nfunc validExponent(exp uint8) error {\n\tmaxExp := uint(bits.UintSize) - 2\n\tif uint(exp) > maxExp {\n\t\treturn fmt.Errorf(\"exponent %d exceeds platform max %d\", exp, maxExp)\n\t}\n\treturn nil\n}\n\n// func main() {\n//     for _, e := range []uint8{12, 14, 20, 40} {\n//         if err := validExponent(e); err != nil { fmt.Println(err) }\n//     }\n// }","typeGuard":null,"tryCatchPattern":"// Construction returns the error; check it explicitly.\n//\n//   pool, err := mem.NewBinaryTieredBufferPool(12, 14, 20)\n//   if err != nil {\n//       return fmt.Errorf(\"buffer pool init: %w\", err)\n//   }","preventionTips":["Always pass exponents (log2 byte size), never raw byte sizes.","Keep exponents <= 30 if the binary may run on 32-bit platforms.","Unit-test pool construction with the configured exponent set.","Validate user/config-driven exponents before passing them to the constructor."],"tags":["mem","buffer-pool","memory","configuration","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}