19

I want to sent a string as an argument to a function. But some user may enter maybe 100 size string or even larger.

[Q] Inside the function is it possible to check the size of the string and return false if it exceeds the length limit that I have specified.

For example, a user is only allowed to send string which has length of 64 characters, and the contract's function returns throw if the string exceeds the limit of 64 character.

Test.transaction().setVariable("very_large_size_string_entered_65_chars");

For example:

Contract Test{
   String data;
   function setVariable(string str) {
       //check somehow does the string exceeds the character limit.
       data = str;
   }
}

Thank you for your valuable time and help.

alper
  • 8,395
  • 11
  • 63
  • 152

4 Answers4

30

Code for calculating string length in characters

contract utf8StringLength {
    //---------------------BEGIN Code to copy-paste--------------
function utfStringLength(string str) constant returns (uint length)
{
    uint i=0;
    bytes memory string_rep = bytes(str);

    while (i<string_rep.length)
    {
        if (string_rep[i]>>7==0)
            i+=1;
        else if (string_rep[i]>>5==0x6)
            i+=2;
        else if (string_rep[i]>>4==0xE)
            i+=3;
        else if (string_rep[i]>>3==0x1E)
            i+=4;
        else
            //For safety
            i+=1;

        length++;
    }
}

////////////////////END Code to copy-paste///////////////////


//-----------------BEGIN testing stuff code-----------------

string constant hello1= "Привет";
string constant hello2= "Hello";
string constant hello3= "你好";
string constant hello4= "هيلو";
string constant hello5= "مرحبا";


function test() constant
returns
    (uint,
    uint,
    uint,
    uint,
    uint)
{
    return(
        utfStringLength(hello1),
        utfStringLength(hello2),
        utfStringLength(hello3),
        utfStringLength(hello4),
        utfStringLength(hello5)
    );
}
//////////////////END testing stuff code//////////////////////

}


Updated for solc v0.8

function utfStringLength(string memory str) pure internal returns (uint length) {
    uint i=0;
    bytes memory string_rep = bytes(str);
while (i<string_rep.length)
{
    if (string_rep[i]>>7==0)
        i+=1;
    else if (string_rep[i]>>5==bytes1(uint8(0x6)))
        i+=2;
    else if (string_rep[i]>>4==bytes1(uint8(0xE)))
        i+=3;
    else if (string_rep[i]>>3==bytes1(uint8(0x1E)))
        i+=4;
    else
        //For safety
        i+=1;

    length++;
}

}

alper
  • 8,395
  • 11
  • 63
  • 152
Alexey Barsuk
  • 2,259
  • 2
  • 17
  • 25
26

Just check if bytes(str).length is too big.

Mind: This does not show the number of characters! See the answer below if you need to know an exact length of a utf-8 encoded string. This will cost significantly more gas, however. Note that the utf-8 length will be at most the byte length.

questionto42
  • 111
  • 5
Tjaden Hess
  • 37,046
  • 10
  • 91
  • 118
  • 5
    This way you can check th byte-length of string. If string encoding, for example UTF8, number of characters can differ from bytes(str).length – Alexey Barsuk Apr 04 '17 at 01:39
  • This answer should be edited to include Alexey's comment. bytes(str).length does NOT give the intended behavior in some cases, so it must be used with caution. – Symeof Oct 02 '18 at 20:19
  • I would argue that byte-length is the more important metric in most cases, since length in encodings like utf-8 is still upper-bounded by byte length. It seems rather arbitrary to assume that OP is using utf8 or any other particular encoding. – Tjaden Hess Oct 03 '18 at 15:14
1

This method is from ens domains smart contract
A detailed explanation can be found here, https://dev.to/deep1144/how-to-find-length-of-string-in-solidity-from-the-smart-contract-of-ens-415a

// SPDX-License-Identifier: MIT
// Source:
// https://github.com/ensdomains/ens-contracts/blob/master/contracts/ethregistrar/StringUtils.sol
pragma solidity >=0.8.4;

library StringUtils { /** * @dev Returns the length of a given string * * @param s The string to measure the length of * @return The length of the input string */ function strlen(string memory s) internal pure returns (uint256) { uint256 len; uint256 i = 0; uint256 bytelength = bytes(s).length;

    for (len = 0; i < bytelength; len++) {
        bytes1 b = bytes(s)[i];
        if (b < 0x80) {
            i += 1;
        } else if (b < 0xE0) {
            i += 2;
        } else if (b < 0xF0) {
            i += 3;
        } else if (b < 0xF8) {
            i += 4;
        } else if (b < 0xFC) {
            i += 5;
        } else {
            i += 6;
        }
    }
    return len;
}

}

Deep patel
  • 11
  • 1
  • This function has higher gas consumption than simply having bytes(str).length – alper May 22 '22 at 07:59
  • Depending on the use case, if bytes(str).length works for you and no special characters are going to be involved in the string, then definitely use it – Deep patel May 23 '22 at 14:05
-1

stirng is the special kind of array and compatible with bytes. Solidity does not provide much string operation and hence we can rely on bytes to carry out any string related operations like null check, length ...

pls find below the modified code to check for the string limit. If supplied styring lenght is more than required then this funcction would revert the function call.

In ther latest solidity release, 'throw' has deprecated, thats why I have used 'revert'.

pragma solidity ^0.4.4;

contract Test{
   string data;
   uint stringLimit;

   function setVariable(string str)  {
      bytes memory strBytes = bytes(str);
      if(strBytes.length >= stringLimit)
          revert;
      else 
         data = str;
    }
}