@@ -449,14 +449,14 @@ func (plan *scanPlanFail) Scan(src []byte, dst any) error {
449
449
// As a horrible hack try all types to find anything that can scan into dst.
450
450
for oid := range plan .m .oidToType {
451
451
// using planScan instead of Scan or PlanScan to avoid polluting the planned scan cache.
452
- plan := plan .m .planScan (oid , plan .formatCode , dst )
452
+ plan := plan .m .planScan (oid , plan .formatCode , dst , 0 )
453
453
if _ , ok := plan .(* scanPlanFail ); ! ok {
454
454
return plan .Scan (src , dst )
455
455
}
456
456
}
457
457
for oid := range defaultMap .oidToType {
458
458
if _ , ok := plan .m .oidToType [oid ]; ! ok {
459
- plan := plan .m .planScan (oid , plan .formatCode , dst )
459
+ plan := plan .m .planScan (oid , plan .formatCode , dst , 0 )
460
460
if _ , ok := plan .(* scanPlanFail ); ! ok {
461
461
return plan .Scan (src , dst )
462
462
}
@@ -1064,6 +1064,14 @@ func (plan *wrapPtrArrayReflectScanPlan) Scan(src []byte, target any) error {
1064
1064
1065
1065
// PlanScan prepares a plan to scan a value into target.
1066
1066
func (m * Map ) PlanScan (oid uint32 , formatCode int16 , target any ) ScanPlan {
1067
+ return m .planScanDepth (oid , formatCode , target , 0 )
1068
+ }
1069
+
1070
+ func (m * Map ) planScanDepth (oid uint32 , formatCode int16 , target any , depth int ) ScanPlan {
1071
+ if depth > 8 {
1072
+ return & scanPlanFail {m : m , oid : oid , formatCode : formatCode }
1073
+ }
1074
+
1067
1075
oidMemo := m .memoizedScanPlans [oid ]
1068
1076
if oidMemo == nil {
1069
1077
oidMemo = make (map [reflect.Type ][2 ]ScanPlan )
@@ -1073,15 +1081,15 @@ func (m *Map) PlanScan(oid uint32, formatCode int16, target any) ScanPlan {
1073
1081
typeMemo := oidMemo [targetReflectType ]
1074
1082
plan := typeMemo [formatCode ]
1075
1083
if plan == nil {
1076
- plan = m .planScan (oid , formatCode , target )
1084
+ plan = m .planScan (oid , formatCode , target , depth )
1077
1085
typeMemo [formatCode ] = plan
1078
1086
oidMemo [targetReflectType ] = typeMemo
1079
1087
}
1080
1088
1081
1089
return plan
1082
1090
}
1083
1091
1084
- func (m * Map ) planScan (oid uint32 , formatCode int16 , target any ) ScanPlan {
1092
+ func (m * Map ) planScan (oid uint32 , formatCode int16 , target any , depth int ) ScanPlan {
1085
1093
if target == nil {
1086
1094
return & scanPlanFail {m : m , oid : oid , formatCode : formatCode }
1087
1095
}
@@ -1141,7 +1149,7 @@ func (m *Map) planScan(oid uint32, formatCode int16, target any) ScanPlan {
1141
1149
1142
1150
for _ , f := range m .TryWrapScanPlanFuncs {
1143
1151
if wrapperPlan , nextDst , ok := f (target ); ok {
1144
- if nextPlan := m .planScan (oid , formatCode , nextDst ); nextPlan != nil {
1152
+ if nextPlan := m .planScanDepth (oid , formatCode , nextDst , depth + 1 ); nextPlan != nil {
1145
1153
if _ , failed := nextPlan .(* scanPlanFail ); ! failed {
1146
1154
wrapperPlan .SetNext (nextPlan )
1147
1155
return wrapperPlan
@@ -1201,6 +1209,15 @@ func codecDecodeToTextFormat(codec Codec, m *Map, oid uint32, format int16, src
1201
1209
// PlanEncode returns an Encode plan for encoding value into PostgreSQL format for oid and format. If no plan can be
1202
1210
// found then nil is returned.
1203
1211
func (m * Map ) PlanEncode (oid uint32 , format int16 , value any ) EncodePlan {
1212
+ return m .planEncodeDepth (oid , format , value , 0 )
1213
+ }
1214
+
1215
+ func (m * Map ) planEncodeDepth (oid uint32 , format int16 , value any , depth int ) EncodePlan {
1216
+ // Guard against infinite recursion.
1217
+ if depth > 8 {
1218
+ return nil
1219
+ }
1220
+
1204
1221
oidMemo := m .memoizedEncodePlans [oid ]
1205
1222
if oidMemo == nil {
1206
1223
oidMemo = make (map [reflect.Type ][2 ]EncodePlan )
@@ -1210,15 +1227,15 @@ func (m *Map) PlanEncode(oid uint32, format int16, value any) EncodePlan {
1210
1227
typeMemo := oidMemo [targetReflectType ]
1211
1228
plan := typeMemo [format ]
1212
1229
if plan == nil {
1213
- plan = m .planEncode (oid , format , value )
1230
+ plan = m .planEncode (oid , format , value , depth )
1214
1231
typeMemo [format ] = plan
1215
1232
oidMemo [targetReflectType ] = typeMemo
1216
1233
}
1217
1234
1218
1235
return plan
1219
1236
}
1220
1237
1221
- func (m * Map ) planEncode (oid uint32 , format int16 , value any ) EncodePlan {
1238
+ func (m * Map ) planEncode (oid uint32 , format int16 , value any , depth int ) EncodePlan {
1222
1239
if format == TextFormatCode {
1223
1240
switch value .(type ) {
1224
1241
case string :
@@ -1249,7 +1266,7 @@ func (m *Map) planEncode(oid uint32, format int16, value any) EncodePlan {
1249
1266
1250
1267
for _ , f := range m .TryWrapEncodePlanFuncs {
1251
1268
if wrapperPlan , nextValue , ok := f (value ); ok {
1252
- if nextPlan := m .PlanEncode (oid , format , nextValue ); nextPlan != nil {
1269
+ if nextPlan := m .planEncodeDepth (oid , format , nextValue , depth + 1 ); nextPlan != nil {
1253
1270
wrapperPlan .SetNext (nextPlan )
1254
1271
return wrapperPlan
1255
1272
}
0 commit comments