Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javax.mail.internet.InternetAddress string-argument constructor not being recognized. #3510

Open
HarshSainiJobvite opened this issue Jun 6, 2022 · 2 comments
Labels
will-not-fix Closed as either non-issue or something not planned to be worked on

Comments

@HarshSainiJobvite
Copy link

HarshSainiJobvite commented Jun 6, 2022

Describe the bug
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of javax.mail.internet.InternetAddress (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('test@test.com')

        ValueInstantiator inst = this.getValueInstantiator();
        Class<?> rawTargetType = this.handledType();
        String value = p.getValueAsString();
        if (inst != null && inst.canCreateFromString()) {
            return inst.createFromString(ctxt, value);
        } else {
            CoercionAction act;
            if (value.isEmpty()) {
                act = ctxt.findCoercionAction(this.logicalType(), rawTargetType, CoercionInputShape.EmptyString);
                return this._deserializeFromEmptyString(p, ctxt, act, rawTargetType, "empty String (\"\")");
            } else if (_isBlank(value)) {
                act = ctxt.findCoercionFromBlankString(this.logicalType(), rawTargetType, CoercionAction.Fail);
                return this._deserializeFromEmptyString(p, ctxt, act, rawTargetType, "blank String (all whitespace)");
            } else {
                if (inst != null) {
                    value = value.trim();
                    if (inst.canCreateFromInt() && ctxt.findCoercionAction(LogicalType.Integer, Integer.class, CoercionInputShape.String) == CoercionAction.TryConvert) {
                        return inst.createFromInt(ctxt, this._parseIntPrimitive(ctxt, value));
                    }

                    if (inst.canCreateFromLong() && ctxt.findCoercionAction(LogicalType.Integer, Long.class, CoercionInputShape.String) == CoercionAction.TryConvert) {
                        return inst.createFromLong(ctxt, this._parseLongPrimitive(ctxt, value));
                    }

                    if (inst.canCreateFromBoolean() && ctxt.findCoercionAction(LogicalType.Boolean, Boolean.class, CoercionInputShape.String) == CoercionAction.TryConvert) {
                        String str = value.trim();
                        if ("true".equals(str)) {
                            return inst.createFromBoolean(ctxt, true);
                        }

                        if ("false".equals(str)) {
                            return inst.createFromBoolean(ctxt, false);
                        }
                    }
                }

                return ctxt.handleMissingInstantiator(rawTargetType, inst, ctxt.getParser(), "no String-argument constructor/factory method to deserialize from String value ('%s')", new Object[]{value});
            }
        }
 }

In the above code, default behaviour is throwing MissingInstantiator error, when canCreateFromString resolves to false.

We see the behaviour has changed for 2.6.7 databind version to 2.13.2.2 databind version when canCreateFromString resolves to false.

In 2.6.7, the default behaviour is as below:

        if (this._objectIdReader != null) {
            return this.deserializeFromObjectId(p, ctxt);
        } else if (this._delegateDeserializer != null && !this._valueInstantiator.canCreateFromString()) {
            Object bean = this._valueInstantiator.createUsingDelegate(ctxt, this._delegateDeserializer.deserialize(p, ctxt));
            if (this._injectables != null) {
                this.injectValues(ctxt, bean);
            }

            return bean;
        } else {
            return this._valueInstantiator.createFromString(ctxt, p.getText());
        }
 }

If canCreateFromString is false, the default behaviour of createFromString is execute.

This behaviour change is breaking our application. Is there a workaround for this issue?

Version information
2.13.2.2

To Reproduce
If you have a way to reproduce this with:

  1. javax.mail.internet.InternetAddress being passed as string in JSON data.
  2. Longer example stored somewhere else (diff repo, snippet), add a link
  3. Textual explanation: include here

Expected behavior
The original behaviour should work, for backward compatibility.

Additional context

#1318
FasterXML/jackson-dataformat-xml#254

@HarshSainiJobvite HarshSainiJobvite added the to-evaluate Issue that has been received but not yet evaluated label Jun 6, 2022
@HarshSainiJobvite HarshSainiJobvite changed the title java.mail.internet.InternetAddress string-argument constructor not being recognized. javax.mail.internet.InternetAddress string-argument constructor not being recognized. Jun 6, 2022
@cowtowncoder
Copy link
Member

This could be a regression, or could be a fix if constructor was detected earlier for cases it should not have been. I do not off-hand know what the change here would have been.
This could be related to security concerns on auto-detecting constructors from java.* / javax.* packages, although I do not remember exact details of possible changes.

But one quick question: which Constructor of javax.mail.internet.InternetAddress you think should be auto-detected, based on looking at Javadocs?

Also: it might be useful to know more specifically minor version in which change was observed, assuming this is easy to do.

@cowtowncoder
Copy link
Member

Ok, I think this was due to what I described above, so type was "accidentally" supported. With 2.12 and beyond this does not (and should not) work -- JDK types need explicit support. Partly this is wrt security (to avoid possible unintended "gadget" types), and partly since later JDKs are unlikely to allow access to these constructors via module system without user configuration. So it is better to have explicit support.

Now, it does not look like this type is part of core JDK even in JDK 8 (and definitely not in later modular JDKs).
So it would need to be provided by a module, for whichever API package it is part of.

I will keep this open for now but will annotate with "wont-fix" since there is no plan to change behavior of core jackson-databind itself here.

@cowtowncoder cowtowncoder added will-not-fix Closed as either non-issue or something not planned to be worked on and removed to-evaluate Issue that has been received but not yet evaluated labels Jul 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
will-not-fix Closed as either non-issue or something not planned to be worked on
Projects
None yet
Development

No branches or pull requests

2 participants