Skip to content

Commit 74326bd

Browse files
authored
Update SimpleDataBinder to prevent binding to specific types (#13269)
* Escaped Javadoc special chars Escaping of special chars in Javadoc, such as '<' with '&lt;' Refactoring of code -> Define explicit types and remove unnecessary variable usages. * Fixed Javadoc typos * Update GrailsPrintWriter.java
1 parent 40b4c63 commit 74326bd

File tree

11 files changed

+43
-48
lines changed

11 files changed

+43
-48
lines changed

grails-databinding/src/main/groovy/grails/databinding/BindInitializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class Contact{
3636
}
3737
class User {
3838
&#064;BindInitializer({
39-
obj -> new Contact(account:obj.account)
39+
obj -&gt; new Contact(account:obj.account)
4040
})
4141
Contact contact
4242
Account account

grails-databinding/src/main/groovy/grails/databinding/BindUsing.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@
2828
* When the annotation is applied to a field, the value assigned to the
2929
* annotation should be a Closure which accepts 2 parameters. The first
3030
* parameter is the object that data binding is being applied to. The second
31-
* parameter is a {@link org.grails.databinding.DataBindingSource} containing the values being bound to the object.
31+
* parameter is a {@link grails.databinding.DataBindingSource} containing the values being bound to the object.
3232
* The value returned by the Closure will be bound to the field. The
3333
* following code demonstrates using this technique to bind an upper
3434
* case version of the value in the DataBindingSource to the field.
3535
*
3636
<pre>
3737
class SomeClass {
3838
&#064;BindUsing({
39-
obj, source -> source['name']?.toUpperCase()
39+
obj, source -&gt; source['name']?.toUpperCase()
4040
})
4141
String name
4242
}

grails-databinding/src/main/groovy/grails/databinding/SimpleDataBinder.groovy

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import grails.databinding.initializers.ValueInitializer
2222
import groovy.transform.CompileStatic
2323
import groovy.transform.TypeCheckingMode
2424
import groovy.util.slurpersupport.GPathResult
25+
import org.codehaus.groovy.reflection.CachedMethod
2526
import org.grails.databinding.ClosureValueConverter
2627
import org.grails.databinding.ClosureValueInitializer
2728
import org.grails.databinding.IndexedPropertyReferenceDescriptor
@@ -81,7 +82,7 @@ class SimpleDataBinder implements DataBinder {
8182
Float,
8283
Double,
8384
Character
84-
]
85+
] as List<Class>
8586

8687
static final INDEXED_PROPERTY_REGEX = /(.*)\[\s*([^\s]*)\s*\]\s*$/
8788

@@ -260,14 +261,14 @@ class SimpleDataBinder implements DataBinder {
260261
}
261262

262263
protected boolean isOkToBind(String propName, List whiteList, List blackList) {
263-
'class' != propName && 'classLoader' != propName && 'protectionDomain' != propName && 'metaClass' != propName && !blackList?.contains(propName) && (!whiteList || whiteList.contains(propName) || whiteList.find { it -> it?.toString()?.startsWith(propName + '.')})
264+
'class' != propName && 'classLoader' != propName && 'protectionDomain' != propName && 'metaClass' != propName && 'metaPropertyValues' != propName && 'properties' != propName && !blackList?.contains(propName) && (!whiteList || whiteList.contains(propName) || whiteList.find { it -> it?.toString()?.startsWith(propName + '.')})
264265
}
265266

266267
protected boolean isOkToBind(MetaProperty property, List whitelist, List blacklist) {
267268
isOkToBind(property.name, whitelist, blacklist) &&
268269
(property.type != null) &&
269270
!Modifier.isStatic(property.modifiers) &&
270-
!(ClassLoader.class.isAssignableFrom(property.type) || ProtectionDomain.class.isAssignableFrom(property.type))
271+
!(ClassLoader.class.isAssignableFrom(property.type) || ProtectionDomain.class.isAssignableFrom(property.type) || MetaProperty.class.isAssignableFrom(property.type) || CachedMethod.class.isAssignableFrom(property.type))
271272
}
272273

273274
protected IndexedPropertyReferenceDescriptor getIndexedPropertyReferenceDescriptor(propName) {
@@ -498,7 +499,7 @@ class SimpleDataBinder implements DataBinder {
498499
* @see BindingFormat
499500
*/
500501
protected ValueConverter getFormattedConverter(Field field, String formattingValue) {
501-
def converter
502+
ValueConverter converter
502503
def formattedConverter = formattedValueConversionHelpers[field.type]
503504
if (formattedConverter) {
504505
converter = { SimpleMapDataBindingSource source ->
@@ -517,7 +518,7 @@ class SimpleDataBinder implements DataBinder {
517518
Field field = null
518519
try {
519520
field = clazz.getDeclaredField(fieldName)
520-
} catch (NoSuchFieldException nsfe) {
521+
} catch (NoSuchFieldException ignored) {
521522
def superClass = clazz.getSuperclass()
522523
if(superClass != Object) {
523524
field = getField(superClass, fieldName)
@@ -527,7 +528,7 @@ class SimpleDataBinder implements DataBinder {
527528
}
528529

529530
protected ValueConverter getValueConverterForField(obj, String propName) {
530-
def converter
531+
ValueConverter converter
531532
try {
532533
def field = getField(obj.getClass(), propName)
533534
if (field) {
@@ -545,9 +546,9 @@ class SimpleDataBinder implements DataBinder {
545546
}
546547
}
547548
}
548-
} catch (Exception e) {
549+
return converter
550+
} catch (Exception ignored) {
549551
}
550-
converter
551552
}
552553

553554
/**
@@ -556,11 +557,9 @@ class SimpleDataBinder implements DataBinder {
556557
*/
557558
protected Class getValueOfBindUsing(Annotation annotation) {
558559
assert annotation instanceof BindUsing
559-
def value
560-
if(annotation instanceof BindUsing) {
561-
value = ((BindUsing)annotation).value()
560+
if (annotation instanceof BindUsing) {
561+
return ((BindUsing) annotation).value()
562562
}
563-
value
564563
}
565564

566565
/**
@@ -569,21 +568,19 @@ class SimpleDataBinder implements DataBinder {
569568
*/
570569
protected String getFormatString(Annotation annotation) {
571570
assert annotation instanceof BindingFormat
572-
String formatString
573-
if(annotation instanceof BindingFormat) {
574-
formatString = ((BindingFormat)annotation).value()
571+
if (annotation instanceof BindingFormat) {
572+
return ((BindingFormat) annotation).value()
575573
}
576-
formatString
577574
}
578575

579576
protected ValueConverter getValueConverterForClass(obj, String propName) {
580-
def converter
577+
ValueConverter converter
581578
def objClass = obj.getClass()
582579
def annotation = objClass.getAnnotation(BindUsing)
583580
if (annotation) {
584581
def valueClass = getValueOfBindUsing(annotation)
585582
if (BindingHelper.isAssignableFrom(valueClass)) {
586-
BindingHelper dataConverter = (BindingHelper)valueClass.newInstance()
583+
BindingHelper dataConverter = (BindingHelper) valueClass.getDeclaredConstructor().newInstance()
587584
converter = new ClosureValueConverter(converterClosure: { DataBindingSource it -> dataConverter.getPropertyValue(obj, propName, it) })
588585
}
589586
}
@@ -762,7 +759,7 @@ class SimpleDataBinder implements DataBinder {
762759
}
763760

764761
protected ValueInitializer getValueInitializerForField(obj, String propName) {
765-
def initializer
762+
ValueInitializer initializer
766763
try {
767764
def field = getField(obj.getClass(), propName)
768765
if (field) {
@@ -819,7 +816,7 @@ class SimpleDataBinder implements DataBinder {
819816
bind obj, new SimpleMapDataBindingSource(value)
820817
return obj
821818
} else if (Enum.isAssignableFrom(typeToConvertTo) && value instanceof String) {
822-
return convertStringToEnum(typeToConvertTo, value)
819+
return convertStringToEnum((Class<? extends Enum>) typeToConvertTo, value)
823820
}
824821
typeToConvertTo.newInstance value
825822
}

grails-databinding/src/main/groovy/grails/databinding/StructuredBindingEditor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@
2121
* into an object. Typically a structured editor will pull
2222
* several values out of the Map that are necessary to initialize
2323
* the state of the object.
24-
<pre>
24+
<code>
2525
class Address {
2626
String state
2727
String city
2828
}
2929
class StructuredAddressBindingEditor implements StructuredBindingEditor {
3030
31-
public Object getPropertyValue(Object obj, String propertyName, Map<String, Object> source) {
31+
public Object getPropertyValue(Object obj, String propertyName, Map&lt;String, Object&gt; source) {
3232
def address = new Address()
3333
3434
address.state = source[propertyName + '_someState']
@@ -58,7 +58,7 @@ binder.registerStructuredEditor Address, new StructuredAddressBindingEditor()
5858
assert resident.workAddress
5959
assert resident.workAddress.state == "Scott's Work State"
6060
assert resident.workAddress.city == null
61-
</pre>
61+
</code>
6262
*
6363
* @author Jeff Brown
6464
* @since 3.0

grails-databinding/src/main/groovy/grails/databinding/converters/FormattedValueConverter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ Class getTargetType() {
4141
* @author Jeff Brown
4242
* @since 3.0
4343
* @see grails.databinding.BindingFormat
44-
* @see org.grails.databinding.SimpleDataBinder
45-
* @see org.grails.databinding.SimpleDataBinder#registerFormattedValueConverter(FormattedValueConverter)
44+
* @see grails.databinding.SimpleDataBinder
45+
* @see grails.databinding.SimpleDataBinder#registerFormattedValueConverter(FormattedValueConverter)
4646
*/
4747
public interface FormattedValueConverter {
4848
/**

grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ protected Writer unwrapWriter(Writer writer) {
9393
}
9494

9595
/**
96-
* Provides Groovy << left shift operator, but intercepts call to make sure
96+
* Provides Groovy &lt;&lt; left shift operator, but intercepts call to make sure
9797
* nulls are converted to "" strings
9898
*
9999
* @param obj The value

grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBuffer.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@
8181
*
8282
* <p>
8383
* StreamCharBuffer keeps the buffer in a linked list of "chunks". The main
84-
* difference compared to JDK in-memory buffers (StringBuffer, StringBuilder &
84+
* difference compared to JDK in-memory buffers (StringBuffer, StringBuilder and
8585
* StringWriter) is that the buffer can be held in several smaller buffers
8686
* ("chunks" here). In JDK in-memory buffers, the buffer has to be expanded
8787
* whenever it gets filled up. The old buffer's data is copied to the new one
8888
* and the old one is discarded. In StreamCharBuffer, there are several ways to
89-
* prevent unnecessary allocation & copy operations. The StreamCharBuffer
89+
* prevent unnecessary allocation and copy operations. The StreamCharBuffer
9090
* contains a linked list of different type of chunks: char arrays,
9191
* java.lang.String chunks and other StreamCharBuffers as sub chunks. A
9292
* StringChunk is appended to the linked list whenever a java.lang.String of a
@@ -101,13 +101,11 @@
101101
*
102102
* for example this line of code in a taglib would just append the buffer
103103
* returned from the body closure evaluation to the buffer of the taglib:<br>
104-
* <code>
105-
* out << body()
106-
* </code><br>
104+
* <code>out &lt;&lt; body()</code>
105+
* <br>
107106
* other example:<br>
108-
* <code>
109-
* out << g.render(template: '/some/template', model:[somebean: somebean])
110-
* </code><br>
107+
* <code>out &lt;&lt; g.render(template: '/some/template', model:[somebean: somebean])</code>
108+
* <br>
111109
* There's no extra java.lang.String generation overhead.
112110
*
113111
* </p>
@@ -128,8 +126,8 @@
128126
*
129127
* <p>
130128
* There's also several other options for reading data:<br>
131-
* {@link #readAsCharArray()} reads the buffer to a char[] array<br>
132-
* {@link #readAsString()} reads the buffer and wraps the char[] data as a
129+
* readAsCharArray()reads the buffer to a char[] array<br>
130+
* readAsString() reads the buffer and wraps the char[] data as a
133131
* String<br>
134132
* {@link #writeTo(Writer)} writes the buffer to a java.io.Writer<br>
135133
* {@link #toCharArray()} returns the buffer as a char[] array, caches the
@@ -156,13 +154,13 @@
156154
* <p>
157155
* StreamCharBuffer keeps the buffer in a linked link of "chunks".<br>
158156
* The main difference compared to JDK in-memory buffers (StringBuffer,
159-
* StringBuilder & StringWriter) is that the buffer can be held in several
157+
* StringBuilder and StringWriter) is that the buffer can be held in several
160158
* smaller buffers ("chunks" here).<br>
161159
* In JDK in-memory buffers, the buffer has to be expanded whenever it gets
162160
* filled up. The old buffer's data is copied to the new one and the old one is
163161
* discarded.<br>
164162
* In StreamCharBuffer, there are several ways to prevent unnecessary allocation
165-
* & copy operations.
163+
* and copy operations.
166164
* </p>
167165
* <p>
168166
* There can be several different type of chunks: char arrays (

grails-web-common/src/main/groovy/org/grails/databinding/bindingsource/DataBindingSourceCreationException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* Thrown if an unrecoverable problem occurs creating a DataBindingSource.
2222
*
2323
* @since 2.3
24-
* @see org.grails.databinding.DataBindingSource
24+
* @see grails.databinding.DataBindingSource
2525
* @see DataBindingSourceCreator
2626
*/
2727
public class DataBindingSourceCreationException extends RuntimeException {

grails-web-common/src/main/groovy/org/grails/web/json/JSONObject.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ of this software and associated documentation files (the "Software"), to deal
7575
* <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
7676
* and if they are not the reserved words <code>true</code>,
7777
* <code>false</code>, or <code>null</code>.</li>
78-
* <li>Keys can be followed by <code>=</code> or <code>=></code> as well as
78+
* <li>Keys can be followed by <code>=</code> or <code>=$gt;</code> as well as
7979
* by <code>:</code>.</li>
8080
* <li>Values can be followed by <code>;</code> <small>(semicolon)</small> as
8181
* well as by <code>,</code> <small>(comma)</small>.</li>
@@ -796,7 +796,7 @@ public JSONObject putOpt(String key, Object value) throws JSONException {
796796

797797
/**
798798
* Produce a string in double quotes with backslash sequences in all the
799-
* right places. A backslash will be inserted within </, allowing JSON
799+
* right places. A backslash will be inserted within &lt;/, allowing JSON
800800
* text to be delivered in HTML. In JSON text, a string cannot contain a
801801
* control character or an unescaped quote or backslash.
802802
*

grails-web-common/src/main/groovy/org/grails/web/servlet/mvc/GrailsWebRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ public GrailsParameterMap getOriginalParams() {
257257
}
258258

259259
/**
260-
* Reset params by re-reading & initializing parameters from request
260+
* Reset params by re-reading and initializing parameters from request
261261
*/
262262
public void resetParams() {
263263
params = (GrailsParameterMap)getOriginalParams().clone();

0 commit comments

Comments
 (0)