Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit bfe0647

Browse files
committed
Add try/finally guards around ThreadLocal state so it resets on exceptions
1 parent 7b4ca20 commit bfe0647

File tree

4 files changed

+120
-38
lines changed

4 files changed

+120
-38
lines changed

src/ServiceStack.Text/Common/WriteDictionary.cs

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -123,22 +123,32 @@ public static void WriteIDictionary(TextWriter writer, object oMap)
123123
JsWriter.WriteItemSeperatorIfRanOnce(writer, ref ranOnce);
124124

125125
JsState.WritingKeyCount++;
126-
JsState.IsWritingValue = false;
127-
128-
if (encodeMapKey)
126+
try
129127
{
130-
JsState.IsWritingValue = true; //prevent ""null""
131-
writer.Write(JsWriter.QuoteChar);
132-
writeKeyFn(writer, key);
133-
writer.Write(JsWriter.QuoteChar);
128+
if (encodeMapKey)
129+
{
130+
JsState.IsWritingValue = true; //prevent ""null""
131+
try
132+
{
133+
writer.Write(JsWriter.QuoteChar);
134+
writeKeyFn(writer, key);
135+
writer.Write(JsWriter.QuoteChar);
136+
}
137+
finally
138+
{
139+
JsState.IsWritingValue = false;
140+
}
141+
}
142+
else
143+
{
144+
writeKeyFn(writer, key);
145+
}
134146
}
135-
else
147+
finally
136148
{
137-
writeKeyFn(writer, key);
149+
JsState.WritingKeyCount--;
138150
}
139151

140-
JsState.WritingKeyCount--;
141-
142152
writer.Write(JsWriter.MapKeySeperator);
143153

144154
if (isNull)
@@ -155,8 +165,14 @@ public static void WriteIDictionary(TextWriter writer, object oMap)
155165
}
156166

157167
JsState.IsWritingValue = true;
158-
writeValueFn(writer, dictionaryValue);
159-
JsState.IsWritingValue = false;
168+
try
169+
{
170+
writeValueFn(writer, dictionaryValue);
171+
}
172+
finally
173+
{
174+
JsState.IsWritingValue = false;
175+
}
160176
}
161177
}
162178

@@ -203,22 +219,33 @@ public static void WriteGenericIDictionary(
203219
JsWriter.WriteItemSeperatorIfRanOnce(writer, ref ranOnce);
204220

205221
JsState.WritingKeyCount++;
206-
JsState.IsWritingValue = false;
207-
208-
if (encodeMapKey)
222+
try
209223
{
210-
JsState.IsWritingValue = true; //prevent ""null""
211-
writer.Write(JsWriter.QuoteChar);
212-
writeKeyFn(writer, kvp.Key);
213-
writer.Write(JsWriter.QuoteChar);
224+
if (encodeMapKey)
225+
{
226+
JsState.IsWritingValue = true; //prevent ""null""
227+
try
228+
{
229+
writer.Write(JsWriter.QuoteChar);
230+
writeKeyFn(writer, kvp.Key);
231+
writer.Write(JsWriter.QuoteChar);
232+
}
233+
finally
234+
{
235+
JsState.IsWritingValue = false;
236+
}
237+
}
238+
else
239+
{
240+
writeKeyFn(writer, kvp.Key);
241+
}
242+
214243
}
215-
else
244+
finally
216245
{
217-
writeKeyFn(writer, kvp.Key);
246+
JsState.WritingKeyCount--;
218247
}
219248

220-
JsState.WritingKeyCount--;
221-
222249
writer.Write(JsWriter.MapKeySeperator);
223250

224251
if (isNull)
@@ -228,8 +255,14 @@ public static void WriteGenericIDictionary(
228255
else
229256
{
230257
JsState.IsWritingValue = true;
231-
writeValueFn(writer, kvp.Value);
232-
JsState.IsWritingValue = false;
258+
try
259+
{
260+
writeValueFn(writer, kvp.Value);
261+
}
262+
finally
263+
{
264+
JsState.IsWritingValue = false;
265+
}
233266
}
234267
}
235268

src/ServiceStack.Text/Common/WriteType.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -420,15 +420,21 @@ public static void WriteProperties(TextWriter writer, object value)
420420
writer.Write(JsWriter.MapKeySeperator);
421421

422422
if (typeof(TSerializer) == typeof(JsonTypeSerializer)) JsState.IsWritingValue = true;
423-
if (propertyValue == null)
423+
try
424424
{
425-
writer.Write(JsonUtils.Null);
425+
if (propertyValue == null)
426+
{
427+
writer.Write(JsonUtils.Null);
428+
}
429+
else
430+
{
431+
propertyWriter.WriteFn(writer, propertyValue);
432+
}
426433
}
427-
else
434+
finally
428435
{
429-
propertyWriter.WriteFn(writer, propertyValue);
430-
}
431-
if (typeof(TSerializer) == typeof(JsonTypeSerializer)) JsState.IsWritingValue = false;
436+
if (typeof(TSerializer) == typeof(JsonTypeSerializer)) JsState.IsWritingValue = false;
437+
}
432438
}
433439
}
434440

src/ServiceStack.Text/QueryStringSerializer.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,28 @@ public static void WriteIDictionary(TextWriter writer, object oMap)
172172
ranOnce = true;
173173

174174
JsState.WritingKeyCount++;
175-
JsState.IsWritingValue = false;
176-
177-
writeKeyFn(writer, key);
175+
try
176+
{
177+
JsState.IsWritingValue = false;
178178

179-
JsState.WritingKeyCount--;
179+
writeKeyFn(writer, key);
180+
}
181+
finally
182+
{
183+
JsState.WritingKeyCount--;
184+
}
180185

181186
writer.Write("=");
182187

183188
JsState.IsWritingValue = true;
184-
writeValueFn(writer, dictionaryValue);
185-
JsState.IsWritingValue = false;
189+
try
190+
{
191+
writeValueFn(writer, dictionaryValue);
192+
}
193+
finally
194+
{
195+
JsState.IsWritingValue = false;
196+
}
186197
}
187198
}
188199
finally

tests/ServiceStack.Text.Tests/DictionaryTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,38 @@ public void Can_deserialize_ordereddictionary_subclass()
593593
Assert.That(deserialized[2], Is.EqualTo("Value3"));
594594
Assert.That(deserialized["Key4"], Is.EqualTo(false));
595595
}
596+
597+
[Test]
598+
public void Can_recover_from_exceptions_when_serializing_dictionary_keys()
599+
{
600+
var before = JsConfig<int>.SerializeFn;
601+
try
602+
{
603+
JsConfig<int>.SerializeFn = v =>
604+
{
605+
throw new Exception("Boom!");
606+
};
607+
var target = new Dictionary<int, string>
608+
{
609+
{ 1, "1" },
610+
};
611+
Assert.Throws<Exception>(() => JsonSerializer.SerializeToString(target));
612+
}
613+
finally
614+
{
615+
JsConfig<int>.SerializeFn = before;
616+
}
617+
var json = JsonSerializer.SerializeToString(new ModelWithDictionary());
618+
619+
json.Print();
620+
621+
Assert.That(json.StartsWith("{"));
622+
}
623+
624+
private class ModelWithDictionary
625+
{
626+
public Dictionary<string, string> Value { get; set; }
627+
}
596628
}
597629

598630
public class OrderedDictionarySub : OrderedDictionary { }

0 commit comments

Comments
 (0)